basic_ads 1.2.0

A bigger release than 1.1.x patch tags: new branch (1.2.x), architectural
overhaul, new features, and a public-API break.

Bug fixes
- Date filtering now works for both `datetime` and legacy `string` field
  storage via hook_views_query_alter(); the old datetime-on-string filters
  silently excluded any ad with a real date.
- The duplicate Views block from the basic_ads_advertisements view's
  block_1 display is hidden via hook_block_alter().

New features
- Block has a new "Number of ads to display" setting (1-50, default 1).
- Weighted random rotation (Efraimidis-Spirakis). Lower field_ad_weight =
  higher priority; each 10 units halves/doubles the relative odds.
  Selection is seeded by the current 60-second time bucket so all viewers
  in a window see the same set (cacheable) and a fresh selection rotates
  in the next minute.
- Placed blocks auto-label as "Basic Ad: {placement name}".
- Friendlier date widgets: datetime_datelist (MDY, 12-hour, 15-minute
  increments).
- field_ad_weight is bounded to (-50, 50).

Architecture / refactoring (BREAKING)
- All procedural hooks moved from basic_ads.module into
  Drupal\basic_ads\Hook\BasicAdsHooks via #[Hook] attributes; the .module
  file is deleted.
- New basic_ads.ad_tracker service owns impression/click recording,
  count/CTR aggregation, and old-data pruning. The previous
  basic_ads_*() global helpers (basic_ads_track_impression,
  basic_ads_track_click, basic_ads_get_*, _basic_ads_anonymize_ip,
  basic_ads_is_user_excluded) are gone. External callers must migrate
  to \Drupal::service('basic_ads.ad_tracker') or the
  Drupal\basic_ads\Service\AdTracker alias.
- Logger DI throughout via LoggerChannelFactoryInterface; exception
  handlers in AdvertisementBlock now log warnings instead of swallowing
  errors.
- Library renamed basic_ads/ad_tracking -> basic_ads/basic_ads, with new
  css/basic-ads.css component CSS.

Update hooks
- 8001 reloads the basic_ads_advertisements view config from the install
  template. Sites that customised the View should export their config
  first; this overwrites it.
- 8002 sets min: -50 / max: 50 on field_ad_weight and refreshes the
  description.
- 8003 switches the date form-display widgets to datetime_datelist.

Migration notes
- Existing placed blocks default to count = 1 (previous view behaviour
  was 5). Bump the new setting on /admin/structure/block as needed.
- field_ad_weight = 0 for everyone by default = uniform random; set
  negative weights on priority ads.
- If migrating from another bundle, stale node-access grants may hide
  ads from anon visitors; resolve with node_access_rebuild().

See CHANGELOG.md for the full notes.