Repository navigation
Releases
0.14.0
Removed
Debounce\YiiCacheDebounceStore(wave M, spec 19 §2.9): it was the core'sDebounce\Psr16DebounceStorewritten
once more over the Yii cache API; the component wiresnew Psr16DebounceStore(new Cache\Psr16Cache($component), $prefix)for adebounce.storenaming a cache component — the same keys, the same window. Migration: code that
constructed it does the same two lines; the class was not in docs/bc.md.Check\RouterCheckandCheck\RecordSampler: therouter.localesline is the core'sCheck\LocalesCheck
(same code, one text for the three adapters that print it: the ok line now names the route parameter, and with an
empty list and no rule asking for every locale the line is not printed — it used to be an ok line), the
--sample-classsampler isConsole\SubjectSamplerofindexnowkit/console(the same class four adapters carried).
Changed
Log\YiiLoggerthrowsPsr\Log\InvalidArgumentExceptionon a level PSR-3 does not define (wave M, spec 19 §3),
as the standard requires ("MUST throw"); it used to log the line at info. Migration: a call with a level of your
own ($logger->log('verbose', …)) must use one of the eight ofPsr\Log\LogLevel.- Wave M, the rest (spec 19):
ActiveRecord\ActiveRecordLoaderextendsConsole\AbstractSubjectLoaderof
indexnowkit/console(its constructor is unchanged);Queue\QueueDispatcheris the push onto the queue component
around the core'sDispatch\BatchingDispatcher(constructor unchanged, the log lines are the core's, the texts this
adapter already printed),Queue\SubmitUrlsJob::newId()delegates toBatchingDispatcher::newJobId();
Url\YiiRouteUrlResolverdecides the locale expansion, the pinned origin and the rebase through the core's
Url\RouteOriginand takes the graph's logger as an appended optional parameter, solocales: 'all'over an empty
router.localesis warned about once per process (it collapsed silently);Check\CacheProbewrites the core's
DebounceStoreCheck::PROBE_KEY(indexnowkit_check, no colon: PSR-16 reserves it) where it wroteindexnowkit:check;
indexnow/statusdescribes the debounce store throughHistory\Adapter\HistoryServices::describeStore()(the same
<id> (<Class>)line as before, shared with Laravel and Yii3);indexnow/sitemapleavessitemap.enabled: false
to the runner (same answer, exit 2) and hands it the graph's clock, so--changed-since "1 day"counts back from a
clockoverride;indexnow/history --limitandkey-generate --lengthfall back toHistoryCommand::DEFAULT_LIMIT
andKeyGenerateCommand::DEFAULT_LENGTHinstead of literals;Config\ConfigFactoryfolds the packages' options
throughOptionalPackage::ownedOptions()/ignoredBlocks(). - The ActiveRecord observer no longer takes the facade:
ActiveRecord\IndexNowObserver::__construct()takes a
Closure(): Adapter\Serviceswhere it took anIndexNowKit, and buildsHook\ObserverHelper::forChanges()from
Services::changes()on the first hook, inside atry/catch. Asave()therefore resolves URLs without building
the client, the transport or the debounce store, and a graph that cannot be built at all is oneerrorline instead
of an exception out ofsave(). Migration: nobody needs to construct the observer — use
Yii::$app->indexnow->observer(); code that did should passfn () => Yii::$app->indexnow->services(). - Configuration errors of the adapter are
IndexNowKit\Exception\ConfigurationException, not Yii's
InvalidConfigException: an override (transport,debounceStore,dispatcher,urlResolver,clock,checks)
that names nothing or the wrong type, aqueue.componentthat is not ayii\queue\Queue, ahistory.storewhose
connection or cache does not resolve,--componentnaming something that is not the component, and the queue job's
"component is not configured in the worker application". Yii's exception is left to what Yii itself throws.
Migration: catchIndexNowKit\Exception\ConfigurationException(it is anInvalidArgumentException). - The clock is a node of the graph: the new
clockcomponent property (PSR-20, an instance, a class or a
component id) reaches the throttle, the debounce window and the submission timestamps, becauseWiringnow
passesServices::clock()to theSubmitterit builds for the pre-flight and toDebounceStoreFactory::fromConfig().
IndexNowKit\Testing\FrozenClockmakes a whole flush deterministic, recorded history included. history.storeis wired by the package:History\Adapter\HistoryServices::storeFor()replaces the adapter's own
twenty lines; the adapter passes only "the PDO of thisdbcomponent" and "a PSR-16 view of this cache component".
The texts and the exception are the same in every adapter (needsindexnowkit/history ^0.3.1).Check\VerifySampleCheckandCheck\SampleOptionsare removed: the core'sCheck\SampleGateCheckand
Check\SampleOptions(codeverify.installed, same lines).IndexNowComponent::$samplesis now the core's type.- An insert is verified against the values the record wrote, an update against the columns it changed, and the core
compares only what every driver spells the same way — a DECIMAL, a date or a JSON document no longer discards the
announcement of a new page. An update or a delete is staged under the subject (Post#7), so a second change of the
same record in one transaction joins the first instead of discarding its URLs.
Added
- The
router.localesline ofindexnow/check(the core'sCheck\LocalesCheck, see "Removed"): it names the
localeslocales: 'all'expands to, and warns whenrouter.localesis empty while a hooked model carries a rule
that asks for all of them. - The
clockcomponent property (see "Changed").
Fixed
- PHP 8.5 without deprecations —
ActiveRecord\IndexNowObserveruses theSplObjectStorageoffset methods
(attach()/contains()are deprecated since 8.5). No runtime change. - Fixed: the component was a fatal without
indexnowkit/sitemap,indexnowkit/verifyorindexnowkit/history
(Class "IndexNowKit\Sitemap\Adapter\SitemapServices" not foundat the first configuration build):
Config\ConfigFactory::factory()andIndexNowComponent::sitemapPackage()/verifyPackage()/historyPackage()
asked the packages'*Services::package()whether the package is installed, and those classes live in the packages.
They now ask the core'sAdapter\OptionalPackage::sitemap()/verify()/history()(core 0.13.0). Same texts,
same properties. A new CI job removes the three packages and boots the application with detection
(OptionalPackagesDetectionTest). - Requires
indexnowkit/core ^0.13,indexnowkit/console ^0.5;indexnowkit/history ^0.4when installed
(HistoryServices::storeFor(); the version cascade of wave L, spec 18 — the Yii2 controller keeps parsing over the
runners, nothing changes here).
0.13.0
Changed
- The optional packages wire themselves:
Yii2\Verify\VerifyServices,Yii2\History\HistoryServicesand
Yii2\Sitemap\SitemapServicesare removed; the component,Wiringand the console actions call
Verify\Adapter\VerifyServices,History\Adapter\HistoryServicesandSitemap\Adapter\SitemapServicesof the
packages (verify 0.3, history 0.3, sitemap 0.7 —conflictwith older ones). What stays here is Yii's: thedb
connection and the cache component behind a store, the queue facts ofstatus, the sample check over Active Record. - Requires
indexnowkit/verify ^0.3,indexnowkit/history ^0.3,indexnowkit/sitemap ^0.7when installed.
0.12.0
Changed
- The
routerblock speaks the core's vocabulary:router.locales,router.locale_parameter,router.set_app_locale
(what the attribute callslocales, whatResolvedUrl::$localeandlocale_hostsare, and what the Laravel adapter has
always used). The pre-0.12 spellingsrouter.languages,router.language_parameterandrouter.set_app_languageare
still read, each with a deprecation warning in the log naming the new key; they go in the next minor. The default GET
parameter stayslanguage(the Yii convention). - Console output goes through
Controller::stdout(): the runners wrote tophp://stdoutdirectly through a
ConsoleOutput, past--color,isColorEnabled()and any controller that redirects or capturesstdout(). The
default output is nowConsole\ControllerOutput(a symfony/consoleOutputover the controller: decorated exactly
when Yii would colour, every write throughstdout()); an injected$output(tests) is untouched. symfony/console
stays a requirement: the runners of indexnowkit/console are written against itsOutputInterface, as Laravel's and
Yii3's consoles are. IndexNowComponent::submitRecords()delegates toIndexNowKit::submitEntities()(core 0.12.0).- Requires
indexnowkit/core ^0.12.
0.11.0
Changed
Queue\QueueDispatcherpushes one job perbatch.max_urlsURLs: a bulk import was one job a queue payload limit
rejected, and every URL was lost with one log line.Cache\Psr16Cachekeeps a storedfalseapart from a miss (an envelope around the value: entries written by 0.10
read as misses once, then are rewritten) and throws the PSR-16InvalidArgumentException(Cache\InvalidKey) for a
key with reserved characters or over 64 characters.checkgetsverify.transport; theverify.dispatchline comes fromVerify\Check\DispatchCheck.- README: a "Verify" step (
php yii indexnow/check) after the model declaration, as the other adapters have. psr/log ^1.1is gone from the constraint (the core requires^2 || ^3).- Requires
indexnowkit/core ^0.11,indexnowkit/console ^0.4; tests againstverify ^0.2,history ^0.2,sitemap ^0.6.
0.10.0
Added
- The
paramExtractornode of the component's graph:new ParamExtractor(new ActiveRecordSubjectReader()), shared by the
resolver, the change handler, the facade andindexnow/explain(Adapter\ServicesBuilder::paramExtractor()).
Changed
- Requires
indexnowkit/core ^0.10; the component no longer registers the reader through the removed static
ParamExtractor::registerReader()(the same accessors resolve the same way; the process-wide flag is gone).
0.9.0
Added
indexnowkit/verifywiring (spec 17 §6.1). Theverifyblock of the component options (enabled,redirect,
non_canonical,origin_error,delay,timeout,max_redirects,max_batch,robots_cache_ttl,user_agent);
with the package andverify.enabled: truethe graph's submitter isVerifyingSubmitterand the commands'
factoryVerifyingSubmitterFactory(Verify\VerifyServices,Wiring), so sync flushes, yii2-queue jobs and the
commands verify. Component:verifyInstalled(predicate override),verifyTransport(the pre-flight transport
override),samples;verifyPackage(),verifyInstalled(),verifyConfig(),verifyEnabled(),
verifyTransport(),robots(),submitterFactory(),unverifiedSubmitterFactory(),events().checklines:
verify.installed,verify.dispatch(warning withdispatch: sync),verify.sample. Without the package the
block is ignored as a whole (checksays so),--sampleis an error naming the install line andverifyConfig()
throws the install line.indexnow/check --sample=a,b/--sample-class=Class,Class:id(comma-separated;Check\SampleOptions,
Check\VerifySampleCheck,Check\RecordSamplerover the controller's loader). A URL with a comma cannot be given.indexnow/config --jsonprints theverifysection when the package is installed.indexnowkit/historywiring (spec 17 §6.2). Thehistoryblock of the component options (store,limit,
key_prefix,pdo.dsn,pdo.service,pdo.table,retention_days); with the package andhistory.store: psr16|pdothe graph's submission store is the package's (History\HistoryServices,Wiring):Psr16SubmissionStore
over the cache component ofdebounce.store(thecachecomponent withmemory/none) throughCache\Psr16Cache,
orPdoSubmissionStoreover the PDO of thedbcomponent named bypdo.service/ a PDO built frompdo.dsn—
never both — so sync flushes, yii2-queue jobs, the commands and the verify decorator record into it; the
submissionStoreproperty still wins. The table is not created (see the package'sdocs/migrations.md).
Component:historyInstalled(predicate override),historyPackage(),historyInstalled(),historyConfig(),
historyEnabled(). Commandsindexnow/history(--host,--status,--url,--since,--limit,--json,
--purge[=days];Console\HistoryAction) andindexnow/status(--jsonper the package'sstatus.schema.json;
the queue component and its class as the adapter facts); without the package both print the install line and
exit 1 (their options are still accepted) andhistoryConfig()throws.checklines:history.installed
(without the package),history.store,history.records.indexnow/config --jsonprints thehistorysection.Config\ConfigFactory::factory()/create()/build()take an appended?bool $verifyInstalled = nulland
?bool $historyInstalled = null.
Changed
- Requires
indexnowkit/core ^0.9,indexnowkit/console ^0.3and (dev/suggest)indexnowkit/sitemap ^0.5,
indexnowkit/verify ^0.1,indexnowkit/history ^0.1. IndexNowControllersubmits--force/--dry-runthroughIndexNowComponent::submitterFactory()(decorated
when verify is on) instead of the graph's plain factory; thesubmittersproperty still overrides it.
0.8.0
Changed
- Requires
indexnowkit/core ^0.8,indexnowkit/console ^0.2and (dev/suggest)indexnowkit/sitemap ^0.4. Core 0.8 strips tracking parameters by default (normalizer.strip_tracking_params) and makesEqualsinparamsan error (see the core changelog).
Added
- The
indexnow/checklines of the adapter carry stable codes (core 0.8,check --json):queue.dispatch,
queue.component,queue.driver,active_record.enabled,url_manager.key_file,url_manager.pretty_url,
url_manager.rule, plus the core'sdebounce.storeandsitemap.installed. Listed in the core'sdocs/check-codes.md. php yii indexnow/check --json(the report as JSON, schemadocs/check.schema.jsonofindexnowkit/console),
--strict(warnings fail the command: put it in the deploy pipeline) and--host=a,b(a list; console 0.2).php yii indexnow/key-generate --forcekeeps the replaced key asINDEXNOW_PREVIOUS_KEYand refuses a second rotation
while it is set;--no-previousand--yesdecide (console 0.2).- The 403 escalation of
Clientcounts in the cache component behinddebounce.store(core 0.8) through the new
Cache\Psr16Cache(ayii\caching\CacheInterfaceas PSR-16): onecriticalline per streak for every worker;
IndexNowComponent::failureCache()returns it (null withmemory/noneor a customdebounceStore). - Component property
submissionStore(instance, class, configuration array or component id of a
Submission\SubmissionStoreInterface; default: nothing is recorded): the store the submitter and the command
submitters record everyResultin (core 0.8);IndexNowComponent::submissionStore()returns it. - Options block
normalizer(strip_tracking_params,tracking_params,trailing_slash,sort_query): the canonical
form of every URL (core 0.8), read throughConfig::OPTIONS. Tracking parameters are stripped by default. php yii indexnow/explain --jsonand thewhenvalues in the text output (console 0.2).php yii indexnow/config(--json): the effective configuration with masked keys plus the component's own option
blocks (console 0.2).IndexNowComponent::EVENT_RESULT(spec 17 §5.7): the component triggers anEvent\ResultEvent($result) for
everyResultof the submitter and of the command submitters, through the PSR-14Event\ResultDispatcherthe
wiring gives the core.
Changed
indexnow/*console actions take-v,-vv,-vvv(andSHELL_VERBOSITY) as symfony/console does; the own
--verboseoption is gone. Migration:php yii indexnow/sitemap --verbose→php yii indexnow/sitemap -v.
0.7.0
Changed
- Requires core 0.7:
Console\SubmitterFactory/Console\SubmitterFactoryInterfaceare now
IndexNowKit\Adapter\SubmitterFactory/IndexNowKit\Adapter\SubmitterFactoryInterface,Console\ResultSummaryis
IndexNowKit\Submission\ResultSummary. Application code that names them (a decorator of thesubmittersproperty ofIndexNowController) changes theuseline; nothing else. - The test suite requires
indexnowkit/testing ^0.1(require-dev): the conformance kits and the H01–H05 assertions
moved there from the core (Testing\Conformance\KeyFileAssertions,CheckOutputAssertions,ReadmeAssertions). - Requires
indexnowkit/console ^0.1: the runners and definitions the console controller are built on moved there from the core
with their FQCN unchanged (IndexNowKit\Console\*); Composer installs it with this package, nothing to do. Sitemap\SitemapSupport(the@internalpredicate with its static override) is gone: the component exposes
sitemapPackage()(anIndexNowKit\Adapter\OptionalPackage) and the new propertysitemapInstalled: ?bool
(nulldetects,falseruns as if the package were absent — tests set it in the component configuration).
Config\ConfigFactory::factory(),create()andbuild()take an appended?bool $sitemapInstalled = null. The
checkline for a configured but ignoredsitemapblock is a warning now (it was ok). The invalid-block critical
line now ends with(run "php yii indexnow/check")(SitemapConfig::loadOrDisabled()).
Documentation
- README: the quick-start record is
tests/Readme/Post.phpverbatim (completeuselines, thecategoryrelation the
via:rule reads, casts/defaults that make it run);ReadmeQuickstartTestcompares the README block with the file
and runs the record through the test application against the FakeTransport. - README: "Notes for AI assistants" (package, minimal complete snippet, verification, pitfalls across the adapters);
ReadmeAiNotesTestkeeps it consistent with the commands and configuration keys. - README "Operations": the production checklist first, then monitoring rules, deleted pages, what not to submit,
multi-domain, queue, commit safety and troubleshooting. - docs/configuration.md: the full core key table with defaults (parity with the Laravel adapter);
docs/testing.md: URLs without HTTP, transactions and verify-on-commit, queue, dry_run, conformance;
docs/multi-domain.md (new): hosts, rules on another host, languages, origin of generated URLs, www and apex,
hreflang; docs/troubleshooting.md: "Sent, but the engine answers" (403/422/429/202), "Duplicates, timing",
"Staging submitted its URLs", "Duplicates withmemoryand several workers". - Russian translation: docs/troubleshooting.ru.md (linked from README.ru.md).
homepagein composer.json points at the docs site (https://indexnowkit.github.io/php/).
0.6.0
Wave 0a of docs/spec/17 with core 0.6.0. indexnow/check fails when YII_ENV (or the component's environment)
is not in production_environments, a key is configured and dry_run is not set (a staging copy with the
production key submits real URLs). A staging or preview environment that submits on purpose sets
'dry_run' => false in the options and gets a warning instead.
Changed
- Requires
indexnowkit/core ^0.6;indexnowkit/sitemap ^0.2when installed.
Added
internetarchiveandamazonaccepted inengines(core 0.6).
Fixed
"app\models\Post" is not an ActiveRecord classnames the base class the command expects; the verify-on-commit
message for a record without a primary key says what to do and what happens meanwhile.
Documentation
- README: the component configuration comes before
key-generate/check(the controller is registered by
bootstrap()); "Why this over X", "Notification, not indexing", the issues link. docs/bc.md:
component options and properties, console actions, bootstrap ids, behavior, job.
0.5.0
Retry-After and the retry.* backoff are honoured by the yii2-queue job, which re-pushes the rejected URLs itself.
Migration: SubmitUrlsJob no longer throws on 429/5xx, so the retry settings of the queue (attempts, ttr
of the driver) do not limit them any more; set retry.max_attempts and the retry.* delays in the component
options instead. Nothing else changes for a 403 (still logged, no retry).
Changed
-
Queue\SubmitUrlsJobre-pushes retryable failures instead of throwing. After a 429, 5xx or network failure the
job pushes a newSubmitUrlsJobwith the rejected URLs, the sameid,attempt + 1and the delay of the core's
Retry\RetryPolicybuilt fromretry.*(Retry-Afterfirst), then ends successfully; atretry.max_attemptsit
logsgiving up on N URL(s) of job <id>at error and ends. New public propertyattempt(1 from the dispatcher).
canRetry()keeps its previous behaviour for exceptions (RetryableSubmissionExceptionwithinmaxAttempts), the
job itself no longer throws it. The sync driver ignores the delay: the attempts run back-to-back in onerun();
indexnow/checksays so. docs/queue.md. -
Internal refactor, no API change: the
Adapter\ServicesBuilderdescription of the graph and thechecklines
moved fromIndexNowComponenttoWiring, the resolution of the override properties toReferences. The
component keeps every public method and property; only relevant if you extend the component's internals.
Fixed
php yii help indexnow/<action>describes the options with the texts and defaults of the core's
Console\Definitions(andSitemap\Console\Definitions), the same the bundle and artisan print:
IndexNowController::getActionOptionsHelp()reads them from the definitions instead of the property docblocks of
the controller.sitemapwithoutindexnowkit/sitemapkeeps Yii's help.