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

php-coveralls / php-coveralls / 3825978059

pending completion
3825978059

push

github

Dariusz Ruminski
some rules

1576 of 1638 relevant lines covered (96.21%)

11.68 hits per line

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

90.44
/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 = [];
18✔
130

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

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

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

158
        return $array;
18✔
159
    }
160

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

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

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

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

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

212
        return $metrics->getLineCoverage();
4✔
213
    }
214

215
    // accessor
216

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

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

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

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

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

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

284
        return $this;
2✔
285
    }
286

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

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

308
        return $this;
2✔
309
    }
310

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

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

332
        return $this;
2✔
333
    }
334

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

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

356
        return $this;
2✔
357
    }
358

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

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

380
        return $this;
2✔
381
    }
382

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

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

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

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

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

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

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

454
        return $this;
4✔
455
    }
456

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

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

478
        return $this;
24✔
479
    }
480

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

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

502
        return $this->metrics;
6✔
503
    }
504

505
    // internal method
506

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

520
        if (is_array($prop)) {
18✔
521
            return $this->toJsonPropertyArray($prop);
18✔
522
        }
523

524
        return $prop;
12✔
525
    }
526

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

538
        foreach ($propArray as $prop) {
18✔
539
            $array[] = $this->toJsonProperty($prop);
4✔
540
        }
9✔
541

542
        return $array;
18✔
543
    }
544

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

574
            // extends by php-coveralls
575
            'serviceJobId' => 'CI_JOB_ID',
18✔
576
            'serviceEventType' => 'COVERALLS_EVENT_TYPE',
18✔
577
            'repoToken' => 'COVERALLS_REPO_TOKEN',
18✔
578
            'parallel' => 'COVERALLS_PARALLEL',
18✔
579
            'flagName' => 'COVERALLS_FLAG_NAME',
18✔
580
        ];
18✔
581

582
        foreach ($map as $propName => $envName) {
18✔
583
            if (isset($env[$envName])) {
18✔
584
                $this->$propName = $env[$envName];
14✔
585
            }
7✔
586
        }
9✔
587

588
        return $this;
18✔
589
    }
590

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

604
        if ($this->requireServiceJobId()) {
16✔
605
            return $this;
4✔
606
        }
607

608
        if ($this->requireServiceNumber()) {
12✔
609
            return $this;
4✔
610
        }
611

612
        if ($this->requireServiceEventType()) {
8✔
613
            return $this;
2✔
614
        }
615

616
        if ($this->requireRepoToken()) {
6✔
617
            return $this;
×
618
        }
619

620
        if ($this->requireGithubActions()) {
6✔
621
            return $this;
2✔
622
        }
623

624
        if ($this->isUnsupportedServiceJob()) {
4✔
625
            return $this;
2✔
626
        }
627

628
        throw new RequirementsNotSatisfiedException();
2✔
629
    }
630

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

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

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

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

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

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

702
    protected function onJsonError()
703
    {
704
        $array = $this->toArray();
×
705

706
        if (!empty($array['git'])) {
×
707
            $this->throwWhenInvalidJson($array['git'], '[git]');
×
708
        }
709

710
        $sourceFiles = empty($array['source_files']) ? [] : $array['source_files'];
×
711

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

717
    /**
718
     * @param array  $item
719
     * @param string $source
720
     */
721
    private function throwWhenInvalidJson(array $item, $source)
722
    {
723
        \json_encode($item);
×
724

725
        if (\json_last_error() !== JSON_ERROR_NONE) {
×
726
            throw new \UnexpectedValueException(sprintf(
×
727
                'Can not encode to JSON, error: "%s" in "%s".',
×
728
                \json_last_error_msg(),
×
729
                $source
730
            ));
×
731
        }
732
    }
733
}
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