Nieuws van politieke partijen over DUS Weert inzichtelijk

39 documenten

Huurders Cwartier doen hun verhaal bij politieke partijen

DUS Weert DUS Weert Weert 24-01-2024 09:39

Een afvaardiging van de huurders van Cwartier komt op 22 januari in de fractievergadering van DUS Weert spreken over de toekomstplannen voor het Beekstraatkwartier. Ook vertegenwoordigers van de fracties CDA, PvdA, D66 en Weert Lokaal waren van de partij. De plannen voor het Beekstraatkwartier hebben nl. directe gevolgen voor Cwartier, een bedrijfsverzamelgebouw waar kleine en middelgrote bedrijven en organisaties onder één dak werken aan innovatie, creatie en sociale kansen.

De huidige huurders begrijpen dat er iets moet gebeuren in dit gebied; ook het gebouw is verouderd en moet opgeknapt en verduurzaamd worden. Omdat de exploitatie binnenkort afloopt is het wel het moment om opnieuw te kijken naar wat er op deze plek mogelijk is.

Men is van mening dat er op dit moment in de plannen van de gemeente een scenario ontbreekt; namelijk het scenario waarin Cwartier als gebouw zoals het nu is ingevuld behouden blijft. Met alle bedrijvigheid, verbindingen, creativiteit, traffic en chemie die daarbij hoort. Het succes wat het nu is; zowel economisch als sociaal-maatschappelijk.

Men geeft aan dat het goed is om te kijken wat er nu al op deze plek is, vraagt namens alle huurders dat de gemeenteraad een zorgvuldige afweging van mogelijke scenario’s maakt en daarbij vooral in het achterhoofd te houden dat iets nieuws per definitie niet beter hoeft te zijn.

Column: Alex in Wonderland – Beheren en Besturen

DUS Weert DUS Weert Weert 22-12-2023 13:11

In zijn 9e column neemt Alex u mee in de wonderlijke wereld van de Weerter politiek.

Voorafgaand aan het Kerstreces (Kerstvakantie) is het een drukke tijd in de politiek. Op de raadsagenda van 20 december staan enkele belangrijke zaken. Hierbij enkele hoogtepunten.

Raadsvoorstel Slotwijziging. Bij het vaststellen van de begroting bepaalt de raad hoeveel geld het college krijgt om de plannen in dat jaar uit te voeren. Wanneer het geld niet wordt besteed kan het college aan de raad vragen om het geld over te hevelen naar het volgende jaar. Bij twee voorstellen fluit de raad het college terug. Het in 2023 niet opgemaakte geld voor klimaatverbetering en de aanpak van het oneigenlijke grondgebruik, samen een kleine €500.000,- mag niet worden overgeheveld omdat er in 2024 volgens de raad genoeg geld beschikbaar is. Het geld moet daarom terug in ‘de spaarpot’ van de gemeente.

Raadsvoorstel project Herijking maatschappelijke voorzieningenstructuur. Bij maatschappelijke voorzieningen moet u denken aan buurthuizen, sporthallen, wijkaccommodaties en culturele centra. De gemeente vraagt zich al jaren af of deze voorzieningen (gebouwen) in de toekomst allemaal in stand kunnen worden gehouden. Daarom wordt er onderzocht welke voorzieningen kunnen blijven bestaan en welke voorzieningen in de toekomst mogelijk dicht moeten. Omdat niemand op z’n geweten wil hebben dat er accommodaties dicht gaan wordt er al jaren om de hete brij heen gedraaid. Zo ook nu. De meningen zijn verdeeld. Doorgaan met het onderzoek of kiezen voor maatwerk oplossingen bij problemen. De verantwoordelijk wethouder wil door met het onderzoek en verdedigt het raadsvoorstel met verve. De raad is echter niet overtuigd. Het raadsvoorstel wordt door een meerderheid van de raad weggestemd. Daarmee is het college terug bij af en ligt het project van de herijking stil.

Verdozing in Weert. Op het oude Philips terrein aan de Industriekade/Kanaalzone komt, tot groot verdriet van de omwonenden en de raad, een mega logistiek centrum. In de volksmond ook wel een ‘doos’ genoemd. In zo een centrum vindt opslag en distributie van producten plaats. Deze activiteiten leiden tot veel extra verkeer in de omgeving. De raad probeert uit alle macht om de vestiging tegen te houden en stelt het college voor om de grond, als gemeente, desnoods aan te kopen. Na wat rekenwerk blijkt een verlies van circa 30 miljoen euro. Dat is zelfs de raad te gortig.

Om te voorkomen dat zo een situatie zich in de toekomst weer voordoet wil de raad van het college daarom de toezegging dat het college zich maximaal in zal spannen om de vestiging van nieuwe logistieke bedrijven te voorkomen. Kortom geen verdere ‘verdozing’ als het even kan. Daartoe dient de raad een ‘redden wat er te redden valt’ motie in. De verantwoordelijk wethouder is van goede wil maar kan niet garanderen dat Weert in de toekomst verschoond blijft van verdere ‘verdozing’. De raad heeft daar geen oren naar een neemt een daartoe ingediende motie unaniem aan. Daarmee bijt het college tijdens deze raadsvergadering opnieuw in het zand.

Een aantal dingen zijn tijdens deze laatste raadsvergadering in 2023 duidelijk geworden:

Het beheer (de zorg en de verantwoordelijkheid) van de aan het college toevertrouwde dossiers is op orde. Het bestuur (leidinggeven, zorgen dat de uitvoering in de juiste richting gaat) kan beter.

De raad laat zich niet meer met een kluitje in het riet sturen.

De net benoemde wethouder Thomas van Gemert zat erbij en keek ernaar. Van Gemert heeft een goed ontwikkelde politieke antenne en heeft, niet onbelangrijk, gevoel voor humor. Wellicht is hij degene die een nieuwe impuls kan geven aan de verbinding tussen College en Raad.

ALEX.

DUS Weert prikte zwerfvuil plus ‘vragen en klachten’ van inwoners op Moesel/Keent

DUS Weert DUS Weert Weert 28-10-2023 19:18

Vanuit het centrale punt bij winkelcentrum Moesel lopen een 7-tal mensen van DUS Weert zaterdag 28 oktober door diverse straten van Moesel en Keent om zwerfvuil te prikken. Daarnaast spreken we op het centrale punt onder het genot van een kopje koffie of thee met inwoners die hun vraag of klacht over hun wijk, straat of de gemeente aan ons kwijt willen.

Een 10-tal inwoners melden zich bij ons. Onderwerpen die ze aan ons kwijt willen gaan vooral over:

het onderhoud van de groenvoorzieningen;

het onderhoud van de straten en de stoepen;

sluipverkeer en te hoge snelheid van verkeer door de wijken;

het gebrek aan handhaving;

de slechte communicatie van de gemeente;

en de slechte klachtenafhandeling door de gemeente.

Naast alle informatie die we bij de inwoners ophaalden werden ook nog eens diverse zakken zwerfafval uit de wijk opgehaald.

Voor DUS Weert een geslaagde dag die we over enige tijd zeker gaan herhalen, maar dan in een andere wijk of dorp. Hou onze social media in de gaten want we komen ook een keer in uw buurt.

Is er nog toekomst voor een logistiek centrum op Kanaalzone-II ?

DUS Weert DUS Weert Weert 26-10-2023 11:34

Wat is het gevolg van het besluit om deze ontwikkeling op Kanaalzone-II toe te staan? Is er als deze ontwikkeling er toch komt sprake van een structurele onomkeerbare ontwrichting van het woon- en leefklimaat van omwonenden en het omringende gebied?

Al vanaf het moment dat bekend wordt dat er een logistiek centrum/warehouses gaan komen op Kanaalzone-II hebben DUS Weert, het CDA en de PvdA kritische vragen gesteld over de wenselijkheid van deze ontwikkeling.

Dit krijgt zijn vervolg in diverse vergaderingen en resulteert in de raadsvergadering van 28 oktober tot een unaniem ingediende motie waarin de voltallige gemeenteraad aangeeft geen vestiging van grootschalige logistieke centra van 4 hectare of groter in het gebied Kanaalzone-II te willen en draagt daarbij het college van B&W op om dit nadrukkelijk te betrekken bij de afwegingen rondom de lopende vergunningsaanvragen.

Gezien de bezwaren vanuit de directe omgeving maar ook die van een groot aantal wijkraden vindt DUS Weert dat mocht het college van B&W besluiten om deze ontwikkeling toch toe te staan, men een heel groot gedeelte van de inwoners van Weert in de kou laat staan.

Straten op Moesel worden toch breder; gemeente gaat de plannen alsnog aanpassen!

DUS Weert DUS Weert Weert 05-10-2023 20:44

Op de inloopbijeenkomst in wijkhuis Moesel wordt donderdagavond duidelijk dat de straten die nu nog moeten worden heringericht zullen worden verbreed van 5,00 naar 5,40 meter; dus 40 cm meer ruimte voor het wegverkeer. Voor de straten die nu inmiddels al vrijwel af zijn, zal worden bekeken of in de toekomst ook een verbreding naar 5,40 meter noodzakelijk is.

Dat de eerder geplande breedte van de rijbaan te smal is, was voor veel aanwonenden al duidelijk vanaf het moment dat de piketpaaltjes de grond in gingen. Met gevolg de halve wijk in rep en roer en een regen van klachten over zowel uitvoering als communicatie bij de gemeente.

Reden genoeg voor de raadsleden Peter Weekers en Aase Wip van DUS Weert om diverse malen kritische vragen te stellen over wat er allemaal misgaat bij de werkzaamheden op Moesel en met het uitdrukkelijke verzoek aan wethouder Winters om op Moesel zo snel mogelijk “de touwtjes in handen” te gaan nemen. Daar hebben de aanwonenden immers recht op!

Column: Alex in Wonderland – Citymarketing Weert – Kroniek van een aangekondigde mislukking

DUS Weert DUS Weert Weert 08-09-2023 13:26

In zijn column – Alex in Wonderland – neemt Alex u mee in de wonderlijke wereld van de Weerter politiek.

Citymarketing Weert – Kroniek van een aangekondigde mislukking

Ineens ligt er dan het raadsvoorstel genaamd Citymarketing Weert. Weert moet als gemeente opnieuw op de kaart worden gezet. Opnieuw? Jazeker. Elke generatie bestuurders heeft nu eenmaal eigen opvattingen over de manier waarop we Weert moeten verkopen aan boeren, burgers en buitenlui.

Parijs heeft de Eiffeltoren. Rome het Colosseum. Londen heeft de Beefeaters en Weert? Weert is Rogstaekersstad en Vlaaienstad. Nu wordt de rog met uitsterven bedreigd en zit Weert (bijna) zonder warme bakkers. Maar dat mag de pret niet drukken.

Terug naar het raadsvoorstel Citymarketing Weert. Voor een paar ton per jaar mag een nog op te tuigen organisatie Weert op de kaart gaan zetten. Wat dat ‘op de kaart zetten’ feitelijk behelst moet nog worden onderzocht en op papier gezet. Dat zien we wel.

En de centjes. Die zijn snel gevonden. Weert heeft immers Centrummanagement. Een goed draaiende organisatie, die de handjes laat wapperen en de binnenstad voorziet van de nodige activiteiten. Winkeliers blij, consumenten blij.

Het gemeentelijk budget van Centrummanagement wordt, met nog wat extra gemeentelijke euro’s, overgeheveld naar citymarketing. Centrummanagement legt vervolgens het loodje en citymarketing kan aan de slag. Een win-win situatie noemen ze dat in het gemeentehuis.

In juli 2022 kondigt de nieuwbakken stichting ‘Weert Marketing’ aan om Weert zowel lokaal als landelijk te gaan promoten. Het ‘merk’ Weert moet ervoor gaan zorgen dat Weert meer bekendheid krijgt. Die bekendheid moet zorgen voor groei. En – last but not least – moeten de Weertenaren trotser worden op de eigen stad.

Hoe men dat gaat doen moet nog worden uitgewerk in een marketingplan, luidt de boodschap. Dat zien we nog wel.

Nog geen jaar later is het kostbare gemeentelijk paradepaardje Weert Marketing echter alweer ter ziele. Wat er precies aan de hand is blijft in nevelen gehuld.

Hoe nu verder? Geen probleem. Er wordt binnenkort door de gemeente een zogenaamde Kwartiermaker aangesteld die moet zorgen voor het optuigen van een nieuwe citymarketingorganisatie. Kosten € 100.000,-. Over ezels en stenen gesproken!

Of Weert met dit geklungel op de kaart wordt gezet mag u zelf beoordelen. Het gemeentebestuur bezorgt zichzelf hiermee op z’n minst een gele kaart.

ALEX.

Wijkgerichte aanpak riolering en het herinrichtingsplan Moesel fase-1: top of flop?

DUS Weert DUS Weert Weert 11-08-2023 20:57

DUS Weert hecht grote waarde aan burgerparticipatie en goede communicatie zeker als projecten een grote impact hebben op de woon- en leefomgeving van de inwoners. Na een rondgang door de wijk blijkt uit gesprekken met bewoners dat er veel vragen en zorgen zijn over de huidige herinrichtingsplannen.

Voor de fractie DUS Weert is dit een reden om een aantal politieke vragen te stellen aan het college van B&W. Deze zogenaamde ‘Vragen Artikel 40 RvO’ moet het college dan binnen 30 dagen beantwoorden.

Ergens in 2020 heeft men besloten om het concept definitief ontwerp te wijzigen naar het definitief. De breedte van de rijbaan versmalt van 5,50 meter naar 5,00 meter.

a) Welke argumenten liggen ten grondslag aan deze wijzigingen?

b) Op wiens initiatief zijn deze wijzigingen doorgevoerd en is dit een gemandateerd besluit of een collegebesluit geweest?

c) Wat zijn de beoogde effecten van het smaller maken van de rijbaan en welke beweegredenen en onderbouwingen liggen hieraan ten grondslag?

d) Welke maatregelen neemt men indien zal blijken dat de doorstroming in de straten wordt belemmerd, er verkeersonveilige situaties en/of parkeerproblemen ontstaan agv. de gekozen weginrichting?

In de eerste voortgangsrapportage Gebiedsontwikkeling van juni 2023 staat “Communicatie is belangrijk onderdeel van project, gelet op lange voorbereidingstijd (plannen dateren van 2019-2020), niet alle bewoners kennen het plan”.

a) Wanneer is er over aanpassingen in de maatvoering van de wegprofielen (wegbreedte, stoepen, groenstroken, parkeerhavens) van concept ontwerp naar definitief ontwerp, vooraf en/of achteraf gecommuniceerd richting gemeenteraad, wijkraad, klankbordgroep en bewoners? Graag een overzicht van alle communicatiemomenten met bijbehorende data.

b) Waarom hebben bewoners nooit de definitieve inrichtingsplannen kunnen inzien op een inloopbijeenkomst? Op het laatst georganiseerde inloopmoment heeft men alléén inzage gehad in de voorlopige ontwerpen (VO) en het concept definitief ontwerp (cDO) die géén definitieve status hebben?

In enkele straten worden bij woningen zonder eigen oprit, de 3- of 4-onder-1-kappers, parkeerhavens aangelegd. Het betreft de Ernst Casimirstraat nrs. 21 en 22 en de Margrietlaan nrs. 42, 44 en 45. Bij de 3-onder-1-kapper van de Irenelaan nr. 42 komt echter geen parkeerhaven. Kan men aangeven op basis van welke argumenten er hier geen parkeerhaven wordt aangelegd terwijl het wel een vergelijkbare situatie betreft?

Is het college bereid om een (nieuwe) klankbordgroep in het leven te roepen die in de uitvoeringsfase kan/mag meedenken over zaken die tijdens de uitvoering voor de wijk van belang kunnen zijn?

Houdt het college vast aan de huidige plannen wanneer in de uitvoeringsfase al blijkt dat de gekozen maatvoering van de rijbaan in een of meerdere straten voor problemen gaat zorgen?

Column: Alex in Wonderland – De Kadernota 2024

DUS Weert DUS Weert Weert 07-07-2023 10:42

In zijn column – Alex in Wonderland – neemt Alex u mee in de wonderlijke wereld van de Weerter politiek.

Wat doe je als je geen problemen hebt? Dan ga je ze maken!

En dat gebeurt dan ook op deze donderdag de 6e juli. De gemeenteraad (de raad) van Weert behandelt de Kadernota 2024. Dat is het boodschappenbriefje dat de raad aan burgemeester en wethouders (b&w) geeft. Met dat boodschappenbriefje stelt b&W dan de begroting (het huishoudboekje) op voor het jaar 2024. Die begroting wordt in november door de raad besproken.

De Kadernota bespreking begint rond 14 uur met het voorlezen van de Algemene Beschouwingen door de politieke partijen (de fracties). Iedereen is lovend over de opzet en de inhoud van de Kadernota voor het jaar 2024. De nota is gemakkelijk leesbaar, de financiën zijn op orde en met de uitvoering van de vele plannen en projecten zit het wel snor het komend jaar. Kortom….we kunnen naar huis.

Maar, zo werkt het natuurlijk niet in de politiek. De partijen in de raad willen met een dertigtal moties (wensen) en amendementen (eisen) nog wat wijzigingen en aanvullingen aanbrengen aan de Kadernota. Een lijstje dat varieert van het schrappen van woordjes, de aanleg van een wandelpad en gratis toegang tot het Museum met de Weerterland pas. Ook verduurzaming, woningbouw en de problemen in de zorg staan hoog op het lijstje van de raad. Een groot gedeelte van de wensen en eisen van de diverse partijen worden door de raad in meerderheid aangenomen. Tegen middernacht sluit voorzitter Vlecken de vergadering. We kunnen nu echt naar huis.

Is er dan verder niets te melden over deze raadsvergadering? Jawel!

Diverse fracties willen vaker in gesprek met de Weertenaren. Het liefst via het organiseren van borrels. Weert Borrelpraat-Stad in het groen.

Twee moties van de raad waarin wordt gevraagd om de komst van logistieke centra (dozenschuivers) te ontmoedigen of te verbieden worden geheel in stijl ‘doorgeschoven’ naar de volgende raadsvergadering.

De gemeente wil het onderhoud van het groen gaan classificeren (indelen in klassen) om de biodiversiteit te bevorderen en tegelijk de kwaliteit van de openbare ruimte te verbeteren. U zult zich afvragen waar gaat dit over? Het komt erop neer dat er creatief wordt bezuinigd op groenonderhoud in woonwijken en op industrieterreinen.

Tot slot nog dit: Onlangs werd er in het Gemeentehuis een ideeënmarkt gehouden. Een van de ideeën was om een omheind hondenspeelveld aan te leggen op de groenstrook bij de Sint Paulusstraat en de Sint Maartenslaan. Dit idee is opgepakt door DUS Weert en via een motie ingebracht bij de Kadernota bespreking. Deze motie is aangenomen. Het hondenspeelveld komt er. Een goede gelegenheid om het beeldje van Manneke Poep aan de Sint Maartenlaan te verplaatsen naar de ingang van het stadhuis.

ALEX.

Fiets en voetgangers oversteek Hushoverweg blijft open

DUS Weert DUS Weert Weert 08-06-2023 08:33

De recente instorting van een stuk riool op de Hushoverweg is voor het college van B&W de aanleiding om dan ook maar meteen de oversteek voor fietsers en voetgangers te sluiten. Dit tot grote verbazing van DUS Weert want volgens hen heeft de sluiting van de oversteek absoluut niks te maken met de instorting en de noodzakelijke rioolrenovatie. Tijdens de raadsvergadering kan Wethouder Winters dan ook geen steekhoudende argumenten aanvoeren waarom deze oversteek gesloten dient te worden.

De verbazing van veel raadsleden is groot want in juni 2020 heeft diezelfde gemeenteraad in meerderheid beslist dat deze oversteek juist open dient te blijven. DUS Weert vraagt zich dan ook af wat het klakkeloos naast zich neerleggen van een eerder genomen besluit van de gemeenteraad doet met het vertrouwen van onze inwoners in de Weerter politiek.

Op initiatief van DUS Weert werd samen met de VVD een amendement opgesteld om de oversteek ook nu niet op te heffen; dit is mede-ingediend door CDA en PvdA. Het amendement is met grote meerderheid van stemmen aangenomen (26 voor en 4 tegen). De oversteek blijft gewoon open!

Slechte stoep, onkruid op straat, lantaarnpaal kapot? Meldt het gemakkelijk met de BuitenBeter-app

DUS Weert DUS Weert Weert 03-05-2023 11:00

! is_object( $post_type ) ) { $post_type = get_post_type_object( $post_type ); } if ( ! empty( $post_type ) && ! empty( $post_type->show_in_rest ) ) { return true; } return false; } /** * Checks if a post can be read. * * Correctly handles posts with the inherit status. * * @since 4.7.0 * * @param WP_Post $post Post object. * @return bool Whether the post can be read. */ public function check_read_permission( $post ) { $post_type = get_post_type_object( $post->post_type ); if ( ! $this->check_is_post_type_allowed( $post_type ) ) { return false; } // Is the post readable? if ( 'publish' === $post->post_status || current_user_can( 'read_post', $post->ID ) ) { return true; } $post_status_obj = get_post_status_object( $post->post_status ); if ( $post_status_obj && $post_status_obj->public ) { return true; } // Can we read the parent if we're inheriting? if ( 'inherit' === $post->post_status && $post->post_parent > 0 ) { $parent = get_post( $post->post_parent ); if ( $parent ) { return $this->check_read_permission( $parent ); } } /* * If there isn't a parent, but the status is set to inherit, assume * it's published (as per get_post_status()). */ if ( 'inherit' === $post->post_status ) { return true; } return false; } /** * Checks if a post can be edited. * * @since 4.7.0 * * @param WP_Post $post Post object. * @return bool Whether the post can be edited. */ protected function check_update_permission( $post ) { $post_type = get_post_type_object( $post->post_type ); if ( ! $this->check_is_post_type_allowed( $post_type ) ) { return false; } return current_user_can( 'edit_post', $post->ID ); } /** * Checks if a post can be created. * * @since 4.7.0 * * @param WP_Post $post Post object. * @return bool Whether the post can be created. */ protected function check_create_permission( $post ) { $post_type = get_post_type_object( $post->post_type ); if ( ! $this->check_is_post_type_allowed( $post_type ) ) { return false; } return current_user_can( $post_type->cap->create_posts ); } /** * Checks if a post can be deleted. * * @since 4.7.0 * * @param WP_Post $post Post object. * @return bool Whether the post can be deleted. */ protected function check_delete_permission( $post ) { $post_type = get_post_type_object( $post->post_type ); if ( ! $this->check_is_post_type_allowed( $post_type ) ) { return false; } return current_user_can( 'delete_post', $post->ID ); } /** * Prepares a single post output for response. * * @since 4.7.0 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * * @param WP_Post $item Post object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ public function prepare_item_for_response( $item, $request ) { // Restores the more descriptive, specific name for use within this method. $post = $item; $GLOBALS['post'] = $post; setup_postdata( $post ); $fields = $this->get_fields_for_response( $request ); // Base fields for every post. $data = array(); if ( rest_is_field_included( 'id', $fields ) ) { $data['id'] = $post->ID; } if ( rest_is_field_included( 'date', $fields ) ) { $data['date'] = $this->prepare_date_response( $post->post_date_gmt, $post->post_date ); } if ( rest_is_field_included( 'date_gmt', $fields ) ) { /* * For drafts, `post_date_gmt` may not be set, indicating that the date * of the draft should be updated each time it is saved (see #38883). * In this case, shim the value based on the `post_date` field * with the site's timezone offset applied. */ if ( '0000-00-00 00:00:00' === $post->post_date_gmt ) { $post_date_gmt = get_gmt_from_date( $post->post_date ); } else { $post_date_gmt = $post->post_date_gmt; } $data['date_gmt'] = $this->prepare_date_response( $post_date_gmt ); } if ( rest_is_field_included( 'guid', $fields ) ) { $data['guid'] = array( /** This filter is documented in wp-includes/post-template.php */ 'rendered' => apply_filters( 'get_the_guid', $post->guid, $post->ID ), 'raw' => $post->guid, ); } if ( rest_is_field_included( 'modified', $fields ) ) { $data['modified'] = $this->prepare_date_response( $post->post_modified_gmt, $post->post_modified ); } if ( rest_is_field_included( 'modified_gmt', $fields ) ) { /* * For drafts, `post_modified_gmt` may not be set (see `post_date_gmt` comments * above). In this case, shim the value based on the `post_modified` field * with the site's timezone offset applied. */ if ( '0000-00-00 00:00:00' === $post->post_modified_gmt ) { $post_modified_gmt = gmdate( 'Y-m-d H:i:s', strtotime( $post->post_modified ) - ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ); } else { $post_modified_gmt = $post->post_modified_gmt; } $data['modified_gmt'] = $this->prepare_date_response( $post_modified_gmt ); } if ( rest_is_field_included( 'password', $fields ) ) { $data['password'] = $post->post_password; } if ( rest_is_field_included( 'slug', $fields ) ) { $data['slug'] = $post->post_name; } if ( rest_is_field_included( 'status', $fields ) ) { $data['status'] = $post->post_status; } if ( rest_is_field_included( 'type', $fields ) ) { $data['type'] = $post->post_type; } if ( rest_is_field_included( 'link', $fields ) ) { $data['link'] = get_permalink( $post->ID ); } if ( rest_is_field_included( 'title', $fields ) ) { $data['title'] = array(); } if ( rest_is_field_included( 'title.raw', $fields ) ) { $data['title']['raw'] = $post->post_title; } if ( rest_is_field_included( 'title.rendered', $fields ) ) { add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); $data['title']['rendered'] = get_the_title( $post->ID ); remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); } $has_password_filter = false; if ( $this->can_access_password_content( $post, $request ) ) { $this->password_check_passed[ $post->ID ] = true; // Allow access to the post, permissions already checked before. add_filter( 'post_password_required', array( $this, 'check_password_required' ), 10, 2 ); $has_password_filter = true; } if ( rest_is_field_included( 'content', $fields ) ) { $data['content'] = array(); } if ( rest_is_field_included( 'content.raw', $fields ) ) { $data['content']['raw'] = $post->post_content; } if ( rest_is_field_included( 'content.rendered', $fields ) ) { /** This filter is documented in wp-includes/post-template.php */ $data['content']['rendered'] = post_password_required( $post ) ? '' : apply_filters( 'the_content', $post->post_content ); } if ( rest_is_field_included( 'content.protected', $fields ) ) { $data['content']['protected'] = (bool) $post->post_password; } if ( rest_is_field_included( 'content.block_version', $fields ) ) { $data['content']['block_version'] = block_version( $post->post_content ); } if ( rest_is_field_included( 'excerpt', $fields ) ) { /** This filter is documented in wp-includes/post-template.php */ $excerpt = apply_filters( 'get_the_excerpt', $post->post_excerpt, $post ); /** This filter is documented in wp-includes/post-template.php */ $excerpt = apply_filters( 'the_excerpt', $excerpt ); $data['excerpt'] = array( 'raw' => $post->post_excerpt, 'rendered' => post_password_required( $post ) ? '' : $excerpt, 'protected' => (bool) $post->post_password, ); } if ( $has_password_filter ) { // Reset filter. remove_filter( 'post_password_required', array( $this, 'check_password_required' ) ); } if ( rest_is_field_included( 'author', $fields ) ) { $data['author'] = (int) $post->post_author; } if ( rest_is_field_included( 'featured_media', $fields ) ) { $data['featured_media'] = (int) get_post_thumbnail_id( $post->ID ); } if ( rest_is_field_included( 'parent', $fields ) ) { $data['parent'] = (int) $post->post_parent; } if ( rest_is_field_included( 'menu_order', $fields ) ) { $data['menu_order'] = (int) $post->menu_order; } if ( rest_is_field_included( 'comment_status', $fields ) ) { $data['comment_status'] = $post->comment_status; } if ( rest_is_field_included( 'ping_status', $fields ) ) { $data['ping_status'] = $post->ping_status; } if ( rest_is_field_included( 'sticky', $fields ) ) { $data['sticky'] = is_sticky( $post->ID ); } if ( rest_is_field_included( 'template', $fields ) ) { $template = get_page_template_slug( $post->ID ); if ( $template ) { $data['template'] = $template; } else { $data['template'] = ''; } } if ( rest_is_field_included( 'format', $fields ) ) { $data['format'] = get_post_format( $post->ID ); // Fill in blank post format. if ( empty( $data['format'] ) ) { $data['format'] = 'standard'; } } if ( rest_is_field_included( 'meta', $fields ) ) { $data['meta'] = $this->meta->get_value( $post->ID, $request ); } $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); foreach ( $taxonomies as $taxonomy ) { $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; if ( rest_is_field_included( $base, $fields ) ) { $terms = get_the_terms( $post, $taxonomy->name ); $data[ $base ] = $terms ? array_values( wp_list_pluck( $terms, 'term_id' ) ) : array(); } } $post_type_obj = get_post_type_object( $post->post_type ); if ( is_post_type_viewable( $post_type_obj ) && $post_type_obj->public ) { $permalink_template_requested = rest_is_field_included( 'permalink_template', $fields ); $generated_slug_requested = rest_is_field_included( 'generated_slug', $fields ); if ( $permalink_template_requested || $generated_slug_requested ) { if ( ! function_exists( 'get_sample_permalink' ) ) { require_once ABSPATH . 'wp-admin/includes/post.php'; } $sample_permalink = get_sample_permalink( $post->ID, $post->post_title, '' ); if ( $permalink_template_requested ) { $data['permalink_template'] = $sample_permalink[0]; } if ( $generated_slug_requested ) { $data['generated_slug'] = $sample_permalink[1]; } } } $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); // Wrap the data in a response object. $response = rest_ensure_response( $data ); if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { $links = $this->prepare_links( $post ); $response->add_links( $links ); if ( ! empty( $links['self']['href'] ) ) { $actions = $this->get_available_actions( $post, $request ); $self = $links['self']['href']; foreach ( $actions as $rel ) { $response->add_link( $rel, $self ); } } } /** * Filters the post data for a REST API response. * * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. * * Possible hook names include: * * - `rest_prepare_post` * - `rest_prepare_page` * - `rest_prepare_attachment` * * @since 4.7.0 * * @param WP_REST_Response $response The response object. * @param WP_Post $post Post object. * @param WP_REST_Request $request Request object. */ return apply_filters( "rest_prepare_{$this->post_type}", $response, $post, $request ); } /** * Overwrites the default protected title format. * * By default, WordPress will show password protected posts with a title of * "Protected: %s", as the REST API communicates the protected status of a post * in a machine readable format, we remove the "Protected: " prefix. * * @since 4.7.0 * * @return string Protected title format. */ public function protected_title_format() { return '%s'; } /** * Prepares links for the request. * * @since 4.7.0 * * @param WP_Post $post Post object. * @return array Links for the given post. */ protected function prepare_links( $post ) { // Entity meta. $links = array( 'self' => array( 'href' => rest_url( rest_get_route_for_post( $post->ID ) ), ), 'collection' => array( 'href' => rest_url( rest_get_route_for_post_type_items( $this->post_type ) ), ), 'about' => array( 'href' => rest_url( 'wp/v2/types/' . $this->post_type ), ), ); if ( ( in_array( $post->post_type, array( 'post', 'page' ), true ) || post_type_supports( $post->post_type, 'author' ) ) && ! empty( $post->post_author ) ) { $links['author'] = array( 'href' => rest_url( 'wp/v2/users/' . $post->post_author ), 'embeddable' => true, ); } if ( in_array( $post->post_type, array( 'post', 'page' ), true ) || post_type_supports( $post->post_type, 'comments' ) ) { $replies_url = rest_url( 'wp/v2/comments' ); $replies_url = add_query_arg( 'post', $post->ID, $replies_url ); $links['replies'] = array( 'href' => $replies_url, 'embeddable' => true, ); } if ( in_array( $post->post_type, array( 'post', 'page' ), true ) || post_type_supports( $post->post_type, 'revisions' ) ) { $revisions = wp_get_latest_revision_id_and_total_count( $post->ID ); $revisions_count = ! is_wp_error( $revisions ) ? $revisions['count'] : 0; $revisions_base = sprintf( '/%s/%s/%d/revisions', $this->namespace, $this->rest_base, $post->ID ); $links['version-history'] = array( 'href' => rest_url( $revisions_base ), 'count' => $revisions_count, ); if ( $revisions_count > 0 ) { $links['predecessor-version'] = array( 'href' => rest_url( $revisions_base . '/' . $revisions['latest_id'] ), 'id' => $revisions['latest_id'], ); } } $post_type_obj = get_post_type_object( $post->post_type ); if ( $post_type_obj->hierarchical && ! empty( $post->post_parent ) ) { $links['up'] = array( 'href' => rest_url( rest_get_route_for_post( $post->post_parent ) ), 'embeddable' => true, ); } // If we have a featured media, add that. $featured_media = get_post_thumbnail_id( $post->ID ); if ( $featured_media ) { $image_url = rest_url( rest_get_route_for_post( $featured_media ) ); $links['https://api.w.org/featuredmedia'] = array( 'href' => $image_url, 'embeddable' => true, ); } if ( ! in_array( $post->post_type, array( 'attachment', 'nav_menu_item', 'revision' ), true ) ) { $attachments_url = rest_url( rest_get_route_for_post_type_items( 'attachment' ) ); $attachments_url = add_query_arg( 'parent', $post->ID, $attachments_url ); $links['https://api.w.org/attachment'] = array( 'href' => $attachments_url, ); } $taxonomies = get_object_taxonomies( $post->post_type ); if ( ! empty( $taxonomies ) ) { $links['https://api.w.org/term'] = array(); foreach ( $taxonomies as $tax ) { $taxonomy_route = rest_get_route_for_taxonomy_items( $tax ); // Skip taxonomies that are not public. if ( empty( $taxonomy_route ) ) { continue; } $terms_url = add_query_arg( 'post', $post->ID, rest_url( $taxonomy_route ) ); $links['https://api.w.org/term'][] = array( 'href' => $terms_url, 'taxonomy' => $tax, 'embeddable' => true, ); } } return $links; } /** * Gets the link relations available for the post and current user. * * @since 4.9.8 * * @param WP_Post $post Post object. * @param WP_REST_Request $request Request object. * @return array List of link relations. */ protected function get_available_actions( $post, $request ) { if ( 'edit' !== $request['context'] ) { return array(); } $rels = array(); $post_type = get_post_type_object( $post->post_type ); if ( 'attachment' !== $this->post_type && current_user_can( $post_type->cap->publish_posts ) ) { $rels[] = 'https://api.w.org/action-publish'; } if ( current_user_can( 'unfiltered_html' ) ) { $rels[] = 'https://api.w.org/action-unfiltered-html'; } if ( 'post' === $post_type->name ) { if ( current_user_can( $post_type->cap->edit_others_posts ) && current_user_can( $post_type->cap->publish_posts ) ) { $rels[] = 'https://api.w.org/action-sticky'; } } if ( post_type_supports( $post_type->name, 'author' ) ) { if ( current_user_can( $post_type->cap->edit_others_posts ) ) { $rels[] = 'https://api.w.org/action-assign-author'; } } $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); foreach ( $taxonomies as $tax ) { $tax_base = ! empty( $tax->rest_base ) ? $tax->rest_base : $tax->name; $create_cap = is_taxonomy_hierarchical( $tax->name ) ? $tax->cap->edit_terms : $tax->cap->assign_terms; if ( current_user_can( $create_cap ) ) { $rels[] = 'https://api.w.org/action-create-' . $tax_base; } if ( current_user_can( $tax->cap->assign_terms ) ) { $rels[] = 'https://api.w.org/action-assign-' . $tax_base; } } return $rels; } /** * Retrieves the post's schema, conforming to JSON Schema. * * @since 4.7.0 * * @return array Item schema data. */ public function get_item_schema() { if ( $this->schema ) { return $this->add_additional_fields_schema( $this->schema ); } $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => $this->post_type, 'type' => 'object', // Base properties for every Post. 'properties' => array( 'date' => array( 'description' => __( "The date the post was published, in the site's timezone." ), 'type' => array( 'string', 'null' ), 'format' => 'date-time', 'context' => array( 'view', 'edit', 'embed' ), ), 'date_gmt' => array( 'description' => __( 'The date the post was published, as GMT.' ), 'type' => array( 'string', 'null' ), 'format' => 'date-time', 'context' => array( 'view', 'edit' ), ), 'guid' => array( 'description' => __( 'The globally unique identifier for the post.' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'readonly' => true, 'properties' => array( 'raw' => array( 'description' => __( 'GUID for the post, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), 'readonly' => true, ), 'rendered' => array( 'description' => __( 'GUID for the post, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ), ), 'id' => array( 'description' => __( 'Unique identifier for the post.' ), 'type' => 'integer', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), 'link' => array( 'description' => __( 'URL to the post.' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), 'modified' => array( 'description' => __( "The date the post was last modified, in the site's timezone." ), 'type' => 'string', 'format' => 'date-time', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'modified_gmt' => array( 'description' => __( 'The date the post was last modified, as GMT.' ), 'type' => 'string', 'format' => 'date-time', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'slug' => array( 'description' => __( 'An alphanumeric identifier for the post unique to its type.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'arg_options' => array( 'sanitize_callback' => array( $this, 'sanitize_slug' ), ), ), 'status' => array( 'description' => __( 'A named status for the post.' ), 'type' => 'string', 'enum' => array_keys( get_post_stati( array( 'internal' => false ) ) ), 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'validate_callback' => array( $this, 'check_status' ), ), ), 'type' => array( 'description' => __( 'Type of post.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), 'password' => array( 'description' => __( 'A password to protect access to the content and excerpt.' ), 'type' => 'string', 'context' => array( 'edit' ), ), ), ); $post_type_obj = get_post_type_object( $this->post_type ); if ( is_post_type_viewable( $post_type_obj ) && $post_type_obj->public ) { $schema['properties']['permalink_template'] = array( 'description' => __( 'Permalink template for the post.' ), 'type' => 'string', 'context' => array( 'edit' ), 'readonly' => true, ); $schema['properties']['generated_slug'] = array( 'description' => __( 'Slug automatically generated from the post title.' ), 'type' => 'string', 'context' => array( 'edit' ), 'readonly' => true, ); } if ( $post_type_obj->hierarchical ) { $schema['properties']['parent'] = array( 'description' => __( 'The ID for the parent of the post.' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), ); } $post_type_attributes = array( 'title', 'editor', 'author', 'excerpt', 'thumbnail', 'comments', 'revisions', 'page-attributes', 'post-formats', 'custom-fields', ); $fixed_schemas = array( 'post' => array( 'title', 'editor', 'author', 'excerpt', 'thumbnail', 'comments', 'revisions', 'post-formats', 'custom-fields', ), 'page' => array( 'title', 'editor', 'author', 'excerpt', 'thumbnail', 'comments', 'revisions', 'page-attributes', 'custom-fields', ), 'attachment' => array( 'title', 'author', 'comments', 'revisions', 'custom-fields', ), ); foreach ( $post_type_attributes as $attribute ) { if ( isset( $fixed_schemas[ $this->post_type ] ) && ! in_array( $attribute, $fixed_schemas[ $this->post_type ], true ) ) { continue; } elseif ( ! isset( $fixed_schemas[ $this->post_type ] ) && ! post_type_supports( $this->post_type, $attribute ) ) { continue; } switch ( $attribute ) { case 'title': $schema['properties']['title'] = array( 'description' => __( 'The title for the post.' ), 'type' => 'object', 'context' => array( 'view', 'edit', 'embed' ), 'arg_options' => array( 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database(). 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database(). ), 'properties' => array( 'raw' => array( 'description' => __( 'Title for the post, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( 'description' => __( 'HTML title for the post, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), ), ); break; case 'editor': $schema['properties']['content'] = array( 'description' => __( 'The content for the post.' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database(). 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database(). ), 'properties' => array( 'raw' => array( 'description' => __( 'Content for the post, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( 'description' => __( 'HTML content for the post, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'block_version' => array( 'description' => __( 'Version of the content block format used by the post.' ), 'type' => 'integer', 'context' => array( 'edit' ), 'readonly' => true, ), 'protected' => array( 'description' => __( 'Whether the content is protected with a password.' ), 'type' => 'boolean', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), ), ); break; case 'author': $schema['properties']['author'] = array( 'description' => __( 'The ID for the author of the post.' ), 'type' => 'integer', 'context' => array( 'view', 'edit', 'embed' ), ); break; case 'excerpt': $schema['properties']['excerpt'] = array( 'description' => __( 'The excerpt for the post.' ), 'type' => 'object', 'context' => array( 'view', 'edit', 'embed' ), 'arg_options' => array( 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database(). 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database(). ), 'properties' => array( 'raw' => array( 'description' => __( 'Excerpt for the post, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( 'description' => __( 'HTML excerpt for the post, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), 'protected' => array( 'description' => __( 'Whether the excerpt is protected with a password.' ), 'type' => 'boolean', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), ), ); break; case 'thumbnail': $schema['properties']['featured_media'] = array( 'description' => __( 'The ID of the featured media for the post.' ), 'type' => 'integer', 'context' => array( 'view', 'edit', 'embed' ), ); break; case 'comments': $schema['properties']['comment_status'] = array( 'description' => __( 'Whether or not comments are open on the post.' ), 'type' => 'string', 'enum' => array( 'open', 'closed' ), 'context' => array( 'view', 'edit' ), ); $schema['properties']['ping_status'] = array( 'description' => __( 'Whether or not the post can be pinged.' ), 'type' => 'string', 'enum' => array( 'open', 'closed' ), 'context' => array( 'view', 'edit' ), ); break; case 'page-attributes': $schema['properties']['menu_order'] = array( 'description' => __( 'The order of the post in relation to other posts.' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), ); break; case 'post-formats': // Get the native post formats and remove the array keys. $formats = array_values( get_post_format_slugs() ); $schema['properties']['format'] = array( 'description' => __( 'The format for the post.' ), 'type' => 'string', 'enum' => $formats, 'context' => array( 'view', 'edit' ), ); break; case 'custom-fields': $schema['properties']['meta'] = $this->meta->get_field_schema(); break; } } if ( 'post' === $this->post_type ) { $schema['properties']['sticky'] = array( 'description' => __( 'Whether or not the post should be treated as sticky.' ), 'type' => 'boolean', 'context' => array( 'view', 'edit' ), ); } $schema['properties']['template'] = array( 'description' => __( 'The theme file to use to display the post.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'validate_callback' => array( $this, 'check_template' ), ), ); $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); foreach ( $taxonomies as $taxonomy ) { $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; if ( array_key_exists( $base, $schema['properties'] ) ) { $taxonomy_field_name_with_conflict = ! empty( $taxonomy->rest_base ) ? 'rest_base' : 'name'; _doing_it_wrong( 'register_taxonomy', sprintf( /* translators: 1: The taxonomy name, 2: The property name, either 'rest_base' or 'name', 3: The conflicting value. */ __( 'The "%1$s" taxonomy "%2$s" property (%3$s) conflicts with an existing property on the REST API Posts Controller. Specify a custom "rest_base" when registering the taxonomy to avoid this error.' ), $taxonomy->name, $taxonomy_field_name_with_conflict, $base ), '5.4.0' ); } $schema['properties'][ $base ] = array( /* translators: %s: Taxonomy name. */ 'description' => sprintf( __( 'The terms assigned to the post in the %s taxonomy.' ), $taxonomy->name ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'context' => array( 'view', 'edit' ), ); } $schema_links = $this->get_schema_links(); if ( $schema_links ) { $schema['links'] = $schema_links; } // Take a snapshot of which fields are in the schema pre-filtering. $schema_fields = array_keys( $schema['properties'] ); /** * Filters the post's schema. * * The dynamic portion of the filter, `$this->post_type`, refers to the * post type slug for the controller. * * Possible hook names include: * * - `rest_post_item_schema` * - `rest_page_item_schema` * - `rest_attachment_item_schema` * * @since 5.4.0 * * @param array $schema Item schema data. */ $schema = apply_filters( "rest_{$this->post_type}_item_schema", $schema ); // Emit a _doing_it_wrong warning if user tries to add new properties using this filter. $new_fields = array_diff( array_keys( $schema['properties'] ), $schema_fields ); if ( count( $new_fields ) > 0 ) { _doing_it_wrong( __METHOD__, sprintf( /* translators: %s: register_rest_field */ __( 'Please use %s to add new schema properties.' ), 'register_rest_field' ), '5.4.0' ); } $this->schema = $schema; return $this->add_additional_fields_schema( $this->schema ); } /** * Retrieves Link Description Objects that should be added to the Schema for the posts collection. * * @since 4.9.8 * * @return array */ protected function get_schema_links() { $href = rest_url( "{$this->namespace}/{$this->rest_base}/{id}" ); $links = array(); if ( 'attachment' !== $this->post_type ) { $links[] = array( 'rel' => 'https://api.w.org/action-publish', 'title' => __( 'The current user can publish this post.' ), 'href' => $href, 'targetSchema' => array( 'type' => 'object', 'properties' => array( 'status' => array( 'type' => 'string', 'enum' => array( 'publish', 'future' ), ), ), ), ); } $links[] = array( 'rel' => 'https://api.w.org/action-unfiltered-html', 'title' => __( 'The current user can post unfiltered HTML markup and JavaScript.' ), 'href' => $href, 'targetSchema' => array( 'type' => 'object', 'properties' => array( 'content' => array( 'raw' => array( 'type' => 'string', ), ), ), ), ); if ( 'post' === $this->post_type ) { $links[] = array( 'rel' => 'https://api.w.org/action-sticky', 'title' => __( 'The current user can sticky this post.' ), 'href' => $href, 'targetSchema' => array( 'type' => 'object', 'properties' => array( 'sticky' => array( 'type' => 'boolean', ), ), ), ); } if ( post_type_supports( $this->post_type, 'author' ) ) { $links[] = array( 'rel' => 'https://api.w.org/action-assign-author', 'title' => __( 'The current user can change the author on this post.' ), 'href' => $href, 'targetSchema' => array( 'type' => 'object', 'properties' => array( 'author' => array( 'type' => 'integer', ), ), ), ); } $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); foreach ( $taxonomies as $tax ) { $tax_base = ! empty( $tax->rest_base ) ? $tax->rest_base : $tax->name; /* translators: %s: Taxonomy name. */ $assign_title = sprintf( __( 'The current user can assign terms in the %s taxonomy.' ), $tax->name ); /* translators: %s: Taxonomy name. */ $create_title = sprintf( __( 'The current user can create terms in the %s taxonomy.' ), $tax->name ); $links[] = array( 'rel' => 'https://api.w.org/action-assign-' . $tax_base, 'title' => $assign_title, 'href' => $href, 'targetSchema' => array( 'type' => 'object', 'properties' => array( $tax_base => array( 'type' => 'array', 'items' => array( 'type' => 'integer', ), ), ), ), ); $links[] = array( 'rel' => 'https://api.w.org/action-create-' . $tax_base, 'title' => $create_title, 'href' => $href, 'targetSchema' => array( 'type' => 'object', 'properties' => array( $tax_base => array( 'type' => 'array', 'items' => array( 'type' => 'integer', ), ), ), ), ); } return $links; } /** * Retrieves the query params for the posts collection. * * @since 4.7.0 * @since 5.4.0 The `tax_relation` query parameter was added. * @since 5.7.0 The `modified_after` and `modified_before` query parameters were added. * * @return array Collection parameters. */ public function get_collection_params() { $query_params = parent::get_collection_params(); $query_params['context']['default'] = 'view'; $query_params['after'] = array( 'description' => __( 'Limit response to posts published after a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', ); $query_params['modified_after'] = array( 'description' => __( 'Limit response to posts modified after a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', ); if ( post_type_supports( $this->post_type, 'author' ) ) { $query_params['author'] = array( 'description' => __( 'Limit result set to posts assigned to specific authors.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); $query_params['author_exclude'] = array( 'description' => __( 'Ensure result set excludes posts assigned to specific authors.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); } $query_params['before'] = array( 'description' => __( 'Limit response to posts published before a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', ); $query_params['modified_before'] = array( 'description' => __( 'Limit response to posts modified before a given ISO8601 compliant date.' ), 'type' => 'string', 'format' => 'date-time', ); $query_params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); $query_params['include'] = array( 'description' => __( 'Limit result set to specific IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { $query_params['menu_order'] = array( 'description' => __( 'Limit result set to posts with a specific menu_order value.' ), 'type' => 'integer', ); } $query_params['offset'] = array( 'description' => __( 'Offset the result set by a specific number of items.' ), 'type' => 'integer', ); $query_params['order'] = array( 'description' => __( 'Order sort attribute ascending or descending.' ), 'type' => 'string', 'default' => 'desc', 'enum' => array( 'asc', 'desc' ), ); $query_params['orderby'] = array( 'description' => __( 'Sort collection by post attribute.' ), 'type' => 'string', 'default' => 'date', 'enum' => array( 'author', 'date', 'id', 'include', 'modified', 'parent', 'relevance', 'slug', 'include_slugs', 'title', ), ); if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { $query_params['orderby']['enum'][] = 'menu_order'; } $post_type = get_post_type_object( $this->post_type ); if ( $post_type->hierarchical || 'attachment' === $this->post_type ) { $query_params['parent'] = array( 'description' => __( 'Limit result set to items with particular parent IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); $query_params['parent_exclude'] = array( 'description' => __( 'Limit result set to all items except those of a particular parent ID.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ); } $query_params['search_columns'] = array( 'default' => array(), 'description' => __( 'Array of column names to be searched.' ), 'type' => 'array', 'items' => array( 'enum' => array( 'post_title', 'post_content', 'post_excerpt' ), 'type' => 'string', ), ); $query_params['slug'] = array( 'description' => __( 'Limit result set to posts with one or more specific slugs.' ), 'type' => 'array', 'items' => array( 'type' => 'string', ), ); $query_params['status'] = array( 'default' => 'publish', 'description' => __( 'Limit result set to posts assigned one or more statuses.' ), 'type' => 'array', 'items' => array( 'enum' => array_merge( array_keys( get_post_stati() ), array( 'any' ) ), 'type' => 'string', ), 'sanitize_callback' => array( $this, 'sanitize_post_statuses' ), ); $query_params = $this->prepare_taxonomy_limit_schema( $query_params ); if ( 'post' === $this->post_type ) { $query_params['sticky'] = array( 'description' => __( 'Limit result set to items that are sticky.' ), 'type' => 'boolean', ); } /** * Filters collection parameters for the posts controller. * * The dynamic part of the filter `$this->post_type` refers to the post * type slug for the controller. * * This filter registers the collection parameter, but does not map the * collection parameter to an internal WP_Query parameter. Use the * `rest_{$this->post_type}_query` filter to set WP_Query parameters. * * @since 4.7.0 * * @param array $query_params JSON Schema-formatted collection parameters. * @param WP_Post_Type $post_type Post type object. */ return apply_filters( "rest_{$this->post_type}_collection_params", $query_params, $post_type ); } /** * Sanitizes and validates the list of post statuses, including whether the * user can query private statuses. * * @since 4.7.0 * * @param string|array $statuses One or more post statuses. * @param WP_REST_Request $request Full details about the request. * @param string $parameter Additional parameter to pass to validation. * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. */ public function sanitize_post_statuses( $statuses, $request, $parameter ) { $statuses = wp_parse_slug_list( $statuses ); // The default status is different in WP_REST_Attachments_Controller. $attributes = $request->get_attributes(); $default_status = $attributes['args']['status']['default']; foreach ( $statuses as $status ) { if ( $status === $default_status ) { continue; } $post_type_obj = get_post_type_object( $this->post_type ); if ( current_user_can( $post_type_obj->cap->edit_posts ) || 'private' === $status && current_user_can( $post_type_obj->cap->read_private_posts ) ) { $result = rest_validate_request_arg( $status, $request, $parameter ); if ( is_wp_error( $result ) ) { return $result; } } else { return new WP_Error( 'rest_forbidden_status', __( 'Status is forbidden.' ), array( 'status' => rest_authorization_required_code() ) ); } } return $statuses; } /** * Prepares the 'tax_query' for a collection of posts. * * @since 5.7.0 * * @param array $args WP_Query arguments. * @param WP_REST_Request $request Full details about the request. * @return array Updated query arguments. */ private function prepare_tax_query( array $args, WP_REST_Request $request ) { $relation = $request['tax_relation']; if ( $relation ) { $args['tax_query'] = array( 'relation' => $relation ); } $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); foreach ( $taxonomies as $taxonomy ) { $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; $tax_include = $request[ $base ]; $tax_exclude = $request[ $base . '_exclude' ]; if ( $tax_include ) { $terms = array(); $include_children = false; $operator = 'IN'; if ( rest_is_array( $tax_include ) ) { $terms = $tax_include; } elseif ( rest_is_object( $tax_include ) ) { $terms = empty( $tax_include['terms'] ) ? array() : $tax_include['terms']; $include_children = ! empty( $tax_include['include_children'] ); if ( isset( $tax_include['operator'] ) && 'AND' === $tax_include['operator'] ) { $operator = 'AND'; } } if ( $terms ) { $args['tax_query'][] = array( 'taxonomy' => $taxonomy->name, 'field' => 'term_id', 'terms' => $terms, 'include_children' => $include_children, 'operator' => $operator, ); } } if ( $tax_exclude ) { $terms = array(); $include_children = false; if ( rest_is_array( $tax_exclude ) ) { $terms = $tax_exclude; } elseif ( rest_is_object( $tax_exclude ) ) { $terms = empty( $tax_exclude['terms'] ) ? array() : $tax_exclude['terms']; $include_children = ! empty( $tax_exclude['include_children'] ); } if ( $terms ) { $args['tax_query'][] = array( 'taxonomy' => $taxonomy->name, 'field' => 'term_id', 'terms' => $terms, 'include_children' => $include_children, 'operator' => 'NOT IN', ); } } } return $args; } /** * Prepares the collection schema for including and excluding items by terms. * * @since 5.7.0 * * @param array $query_params Collection schema. * @return array Updated schema. */ private function prepare_taxonomy_limit_schema( array $query_params ) { $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); if ( ! $taxonomies ) { return $query_params; } $query_params['tax_relation'] = array( 'description' => __( 'Limit result set based on relationship between multiple taxonomies.' ), 'type' => 'string', 'enum' => array( 'AND', 'OR' ), ); $limit_schema = array( 'type' => array( 'object', 'array' ), 'oneOf' => array( array( 'title' => __( 'Term ID List' ), 'description' => __( 'Match terms with the listed IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), ), array( 'title' => __( 'Term ID Taxonomy Query' ), 'description' => __( 'Perform an advanced term query.' ), 'type' => 'object', 'properties' => array( 'terms' => array( 'description' => __( 'Term IDs.' ), 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'default' => array(), ), 'include_children' => array( 'description' => __( 'Whether to include child terms in the terms limiting the result set.' ), 'type' => 'boolean', 'default' => false, ), ), 'additionalProperties' => false, ), ), ); $include_schema = array_merge( array( /* translators: %s: Taxonomy name. */ 'description' => __( 'Limit result set to items with specific terms assigned in the %s taxonomy.' ), ), $limit_schema ); // 'operator' is supported only for 'include' queries. $include_schema['oneOf'][1]['properties']['operator'] = array( 'description' => __( 'Whether items must be assigned all or any of the specified terms.' ), 'type' => 'string', 'enum' => array( 'AND', 'OR' ), 'default' => 'OR', ); $exclude_schema = array_merge( array( /* translators: %s: Taxonomy name. */ 'description' => __( 'Limit result set to items except those with specific terms assigned in the %s taxonomy.' ), ), $limit_schema ); foreach ( $taxonomies as $taxonomy ) { $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; $base_exclude = $base . '_exclude'; $query_params[ $base ] = $include_schema; $query_params[ $base ]['description'] = sprintf( $query_params[ $base ]['description'], $base ); $query_params[ $base_exclude ] = $exclude_schema; $query_params[ $base_exclude ]['description'] = sprintf( $query_params[ $base_exclude ]['description'], $base ); if ( ! $taxonomy->hierarchical ) { unset( $query_params[ $base ]['oneOf'][1]['properties']['include_children'] ); unset( $query_params[ $base_exclude ]['oneOf'][1]['properties']['include_children'] ); } } return $query_params; } }

Zie je content die volgens jou niet op deze site hoort? Check onze disclaimer.