# core/producers/tool.phpcs.producer.ts

> 44 lines of code and 11 definitions.

Tree: GovLab Quality
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-producers-tool-phpcs-producer-ts
Source text: https://banes-lab.com/source/quality/core/producers/tool.phpcs.producer.ts.txt

Listed in [core/producers](https://banes-lab.com/api/source/quality/core/producers.md), after [core/producers/tool.oxlint.producer.ts](https://banes-lab.com/source/quality/core/producers/tool.oxlint.producer.ts.md) and before [core/producers/tool.phpmd.producer.ts](https://banes-lab.com/source/quality/core/producers/tool.phpmd.producer.ts.md).

## Definitions

- `produce` (lexical_declaration, line 35)
- `TOOL` (lexical_declaration, line 8)
- `STANDARDS` (lexical_declaration, line 9)
- `MIN_SEGS` (lexical_declaration, line 10)
- `SKIP_MARKERS` (lexical_declaration, line 11)
- `ruleOf` (lexical_declaration, line 13)
- `text` (lexical_declaration, line 14)
- `segs` (lexical_declaration, line 15)
- `version` (lexical_declaration, line 36)
- `lines` (lexical_declaration, line 37)
- `rules` (lexical_declaration, line 38)

## Contained in

- [core/producers](https://banes-lab.com/anatomy/quality/folder-quality-core-producers.md)

## Uses

- [core/aggregators/catalog.aggregator.ts](https://banes-lab.com/source/quality/core/aggregators/catalog.aggregator.ts.md)

## Linked from

- [core/aggregators](https://banes-lab.com/anatomy/quality/folder-quality-core-aggregators.md)

## Source

```typescript
import type { CatalogProduct, CatalogRule } from "#types/catalog.types";
import { commandOutput, commandVersion } from "#core/adapters/invocation.adapter";
import { byRuleId } from "#core/comparators/rule.comparator";
import { defineProducer } from "#core/registries/producer.registry";
import { distinctRules } from "#core/selectors/catalog.selector";
import { tallyBy } from "#core/aggregators/catalog.aggregator";

const TOOL = "phpcs";
const STANDARDS = "PEAR,PSR1,PSR2,PSR12,Squiz,Zend,Generic";
const MIN_SEGS = 3;
const SKIP_MARKERS = ["(", "---", "contains"];

const ruleOf = function ruleOf(line: string, version: string): CatalogRule[] {
    const text = line.trim();
    const segs = text.split(".");
    if (text === "" || SKIP_MARKERS.some((marker) => text.includes(marker)) || segs.length < MIN_SEGS) {
        return [];
    }
    return [
        {
            canonical: null,
            category: segs[1],
            description: null,
            ecosystem: "php",
            name: segs.at(-1),
            ruleId: text,
            standard: segs[0] ?? "",
            tool: TOOL,
            toolVersion: version,
            url: null,
        },
    ];
};

const produce = async function produce(): Promise<CatalogProduct[]> {
    const version = commandVersion(TOOL, ["--version"]);
    const lines = commandOutput(TOOL, ["-e", `--standard=${STANDARDS}`]).split("\n");
    const rules = distinctRules(lines.flatMap((line) => ruleOf(line, version))).toSorted(byRuleId);
    return [
        {
            rules,
            source: TOOL,
            summary: { byStandard: tallyBy(rules, "standard"), tool: TOOL, toolVersion: version, total: rules.length },
        },
    ];
};

defineProducer({ name: TOOL, produce, refresh: "manual" });
```
