Jump to content


Popular Content

Showing content with the highest reputation since 10/19/2019 in all areas

  1. 27 points
    This version on the dev branch contains 26 commits (relative to 3.0.142) and is focused primarily in resolving reported issues, and we managed to cover 18 of them in this version. Thanks for the reports and help in our GitHub issues repo. This version represents about 2 weeks of work, and ProcessWire Weekly #284 has good coverage of those that occurred last week. More details about this week's updates can be also be found in the dev branch commit log. There are also some other minor additions and improvements in 3.0.143 as well. My favorite are the improvements to our logs system. It now collapses identical log entries that occur near each other. That means a single recurring log entry (like an error message) won't repeat indefinitely in the log and take up a lot of space. Now it just adds a counter to one log entry and updates the timestamp, rather than duplicating the entire log entry... Much more efficient. When you view a log in Setup > Logs, it identifies these collapsed log entries for you. In addition, the output in the "errors" and "exceptions" logs now have improved readability, isolating error messages and filenames from stack traces. Lastly, the ajax navigation in Setup > Logs now shows logs in newest-to-oldest (modification date) rather than alphabetical, which I find a lot more useful. The log at the top of the list is always the one most recently updated. For core updates in coming weeks, I'm primarily focused on preparing the current dev branch to merge to the master branch, as it's been awhile since the last merge and the master branch is itching for a new version. Most of you reading this already run on the dev branch, but there are many out there that also stick to the master branch, and with all the new stuff on the dev branch, I'd like to get our master up-to-date with this as well. Thanks for reading, have a great weekend!
  2. 16 points
    ProcessWire 3.0.144 and 3.0.145 add improved field template context override settings and include a new Inputfields API, along with numerous other issue fixes, optimizations and improvements to the core. This blog post is a continuation (and more in-depth version) of last week's post on 3.0.144 that was in the forum— https://processwire.com/blog/posts/pw-3.0.145/
  3. 5 points
    The Inputfields JS API is really cool, thanks @ryan! What do you think about adding a feature so that some (all??) of these JS functions could be triggered via URL query string parameters? As per my request here it would be neat to be able to create links (e.g. modal) to a form that automatically show/hide/highlight/etc particular fields.
  4. 4 points
    It's not related to ProcessWire. That's the good news. The bad news are: I don't know the answer. 😉 Some say it's related to your hosting provider, some say it's related to a CDN. I found two similar issues out there in the wild: https://wordpress.org/support/topic/unusual-stuff-in-the-url/ https://community.cloudflare.com/t/website-css-not-loading-loads-with-development-mode-on/128163 So... if there is no CDN involved, try to look into your hosting and maybe even ask their support team. Last but not least: Welcome to the forums. 🙂
  5. 4 points
    Ok, my bad. Still, reporting post serves a completely different purpose. Hopefully this will be picked up by someone that can address the issue, but the best is to post the issue on github. You would have to create an account there, and of course that's up to you, but you don't need to use git to do it, only fill a form on the site.
  6. 4 points
    Hi @bernhard, @rjgamer Thanks for the comments - I share some of the frustration you are voicing - but I'm only able to handle issues on the processwire-issues and processwire-requests repos. I don't have admin rights on the main processwire code repo so I can't take any action on PRs, even if I wanted to. Perhaps we could invite @horst to also comment here as he is the only member of the community who I feel has been successful at having bulk code submissions adopted into Processwire.
  7. 3 points
    ProcessWire / Fullcalendar solution including comfortable planning app in the backend: https://vdt-icsa.de/program/ https://2018.tonmeistertagung.com/en/program/
  8. 3 points
    Sadly, the rider of this new horse is dumber than a truck-load of doorstops. So I found another way to accomplish what I was looking for. In my opinion, it's hacky, as I still don't know the answers to my op questions, but it will work for now. The $_FILES['input_file_fieldname']['tmp_name'] works as the parameter to New WireUpload(). The result is a randomly created name saved in both the PageImages and file system. Using Soma's rename procedure to provide the original uploaded file's name corrects that anomaly. The result is an uploaded image with the correct (human readable) name. Anyone want to buy a horse? Only ridden once. Includes a new stick. Cheap.
  9. 3 points
    I think it should be: $page->fixtures->find("team_a=$teamA,team_b=$teamB");
  10. 3 points
    The simple solution is to create a new text field "full_name" and add it to your template. Set the visibility to "Hidden (not shown in the editor)". In /site/ready.php: $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->template == 'your_template') { $page->full_name = $page->first_name . ' ' . $page->last_name; } }); You'll need to save all the pages once to populate the full_name field - if there are a lot then use the API to loop over the pages and save them. Now you can search the full_name field.
  11. 3 points
    The sad truth is that ryan seems to ignore them 😞 I've mentioned that several times but all of my questions where handled like pull requests: ignored. Maybe @netcarver can tell us something more about that topic, as he is taking care about the pw-issues repo. Thx for that btw! 🙂
  12. 3 points
    Thanks - from what I can tell, the backup is being created successfully - it's just not linked to. The new version just committed now returns this with the restore link included and the error color changed to match the PW uikit color and also make links white and underlined so they are visible. You mentioned above that the restore didn't work though, so please test the new version and let me know.
  13. 3 points
    Fieldset (open) (a field) and the Minimal Fieldset module is what I use for things like this.
  14. 2 points
    Have you looked at the $session documentation? If so is there a specific problem you're having?
  15. 2 points
    I need to take a look at that, but unfortunately, I'm not hopeful that I'll find enough time this week. Next week should be a bit less crazy though. I haven't found the time to update to the latest FB release, but it looks like soon will be a good time to do so 🙂 Stay tuned.
  16. 2 points
    Google 'professor messer' and check out a course on Udemy, a course by Chris Bryant for CCNA video bootcamp.
  17. 2 points
    That's not only for PW development but if you've never tried the remote development feature of vscode you should definitely check it out! I'm using it for all SSH related stuff now (server administration) and it's been an awesome experience so far. Compared to the console you get a lot of benefits: open any file directly in vscode for editing ( "code foo.txt" will open foo.txt in vscode ) upload files via drag&drop, download via right click add different folders to your workspace (eg you can attach /var/www/vhosts and /etc/apache2) use ctrl+p to quickly search for files use the GUI to quickly search for any text in any files/folders get a full and awesome GIT integration (+GUI) extremely easy setup, just download the extension, add a host (host + user) and it works (using ssh keys) In the left bottom corner you can see that I'm connected to a remote host. Working on it is just as if it was your local machine 🙂 Intelephense does not work, but I develop locally anyhow and for all server administration stuff there is really everything I need.
  18. 2 points
    If anyone hasn't seen it, https://www.11ty.io is pretty amazing for static sites, it gets a lot of things right in my opinion. Much less opinionated than other static generators, allows swapping template languages on the fly throughout or on a page by page basis, and the systems for page data are super powerful and flexible. I just build a startup marketing site with it, a few of the cool things I did were: read filesystem and parse image files to create a globally accessible images object with width, height, ratio data for use with mixins to ouput lazyload containers; parse a csv file to build a really complicated pricing table... no more client requests to change wording on x row, they just edit a google doc I set up for them, I download and drop in the assets folder, rebuild and done!
  19. 2 points
    Here is a more detailed answer with the steps you have to take: Download the ProcessWire Zip (or use one of the other install methods) Unzip the file in your web root and rename it to the name how your project should be named Open Laragon control panel Click "reload" button for Apache This automatically creates a virtual host with the name of your folder like "processwire.dev" (I don't remember what is the default domain of Laragon, because I changed it to .localhost) You can then navigate in your browser to this URL You will see the ProcessWire installer and just have to follow the steps
  20. 2 points
    Hello, thanks for sharing, for everyone who came here like me and the proposal did not work for some reason, I invite you to read the instructions here: It is also important that they use the following web.config file (which contains minor corrections to the code initially shared by @nikola). I hope it helps you with something like me. Regards!
  21. 2 points
    As you can read in the previous posts there are some issues with the module right now. There haven't been any updates so far in the official repository. So you might have to dig through errors and fix them. Right now I wouldn't recommend this module in any project unless you want to take care of all possible issues. What's the main feature you are looking for? There are several other modules out there so maybe we can find a solution for your needs.
  22. 1 point
    Hi @Peejay, did you run the Additional steps / Install Snipcart products package in SnipWire module settings? This step installs product templates, files, fields and some demo pages required to build a Snipcart product catalogue. This additional step is needed to prevent unintended deletion of your Snipcart products catalogue when main module is uninstalled. In the current alpha version this isn't yet checked by SnipWire. If you did already run the additional step with an earlier SnipWire version there will be fields missing which were added in a later version. So you will need to re-run this step. The missing resources(fields, templates, pages, ...) will then be installed. Existing ones won't be touched! To re-run this step, you will need to edit/remove a key in database directly: DB table: "modules" -> find entry with class "SnipWire" -> edit the "data" field and remove the Json key: "product_package":true (be sure to leave a valid Json string - you will need to also remove the corresponding comma : {"api_key":"YOUR_LIVE_API_KEY","api_key_test":"ODQzZTc1MjktZGQxNy00YmUzLWFkMWYtZDE3MDQ2YTk1ODNjNjM2ODE3NTg5NzUyNDQxOTc0","api_key_secret":"YOUR_LIVE_API_KEY_SECRET","api_key_secret_test":"","snipcart_environment":"0","single_page_shop":"","single_page_shop_page":1,"credit_cards":["visa","mastercard","amex"],"currencies":["eur","usd"],"show_cart_automatically":1,"shipping_same_as_billing":1,"show_continue_shopping":1,"split_firstname_and_lastname":1,"snipcart_debug":1,"snipcart_css_path":"https:\/\/cdn.snipcart.com\/themes\/2.0\/base\/snipcart.min.css","snipcart_css_integrity":"","snipcart_js_path":"https:\/\/cdn.snipcart.com\/scripts\/2.0\/snipcart.js","snipcart_js_integrity":"","include_jquery":"","jquery_js_path":"https:\/\/code.jquery.com\/jquery-3.3.1.min.js","jquery_js_integrity":"sha256-FgpCb\/KJQlLNfOu91ta32o\/NMZxltwRo8QtmkMRdAu8=","excluded_templates":["promailer-email","promailer-subscribe"],"cart_image_width":65,"cart_image_height":65,"cart_image_quality":70,"cart_image_hidpi":1,"cart_image_hidpiQuality":50,"cart_image_cropping":1,"data_item_name_field":"title","uninstall":"","submit_save_module":"Submit","taxes_included":1,"webhooks_endpoint":"\/webhooks\/snipcart","include_snipcart_css":1,"taxes":"[{\"name\":\"20% VAT\",\"numberForInvoice\":\"\",\"rate\":\"0.20\",\"appliesOnShipping\":[]},{\"name\":\"10% VAT\",\"numberForInvoice\":\"\",\"rate\":\"0.10\",\"appliesOnShipping\":[]},{\"name\":\"10% VAT (Shipping)\",\"numberForInvoice\":\"\",\"rate\":\"0.10\",\"appliesOnShipping\":[\"1\"]}]","snipwire_debug":1,"data_item_categories_field":"snipcart_item_categories","product_package":true} After the key is removed, visit the SnipCart module settings again and re-run the product package installer! In the release version of SnipCart, this will be handled automatically. On each update it will check if there are new fields or other resources to be installed. Hope this helps! p.s. You could also completely uninstall the SnipCart module and then reinstall - this should also activate the product package installer link! -- Martin
  23. 1 point
    If you're serious about performance and don't have http2 available, you can optimize a lot with resource hints and service workers + cache API.
  24. 1 point
  25. 1 point
    lol, i see amigo, I just didn't want to have to go re-invent the wheel, ya know? I'm liking this little gem https://fullcalendar.io/ Just gotta figure out the best way to implement it 😉
  26. 1 point
  27. 1 point
  28. 1 point
    Do not use FieldtypeInteger for Phonenumbers, because the Mysql Datatype is INT and therefore the value is limited to 4 bytes strings (32bit). You can use FieldtypeInteger only for numbers within the range from -2147483647 to 2147483647. Use builtin FieldtypeText or FieldtypePhone (3d Party Module) for Phonenumbers. The value of FieldtypePhone must be an instance of Phone (WireData derived object) otherwise it will be set to blank value. From the code: /** * If value not of instance Phone return empty instance */
  29. 1 point
    Hi! It was a cache problem. I leave this topic for any similar issues.
  30. 1 point
    You're welcome. JL2 (when I get there 🙈) will give some more control here. This case would be covered by subscribe/{path} --> @[1495]/{path}, and then there'd either be a {query} wildcard or an option on the jumplink itself to automatically carry it over.
  31. 1 point
    You're a legend - thank you - works perfectly!
  32. 1 point
    @Kiwi Chris Just looked at one of my sites and this is what I put in ready.php // lets non superusers view unpublished and hidden pages in listers // https://processwire.com/talk/topic/9346-not-all-specified-templates-are-editable-only-includehidden-is-allowed/?do=findComment&comment=143068 $this->wire()->addHookBefore('ProcessPageLister::getSelector', function($event) { $event->object->allowIncludeAll = true; }); Does this solve your problems?
  33. 1 point
    Worth noting: https://processwire.com/talk/topic/19912-future-of-padloper-new-project-lead-announcement/ TL;DR: https://processwire.com/talk/topic/19912-future-of-padloper-new-project-lead-announcement/?do=findComment&comment=187487
  34. 1 point
    No solution, but I guess there is definitely something broken. I'm getting error messages like the following on multiple servers of mine: Fatal error: Method SeoMaestro\PageFieldValue::__toString() must not throw an exception, caught ErrorException: chdir(): open_basedir restriction in effect. File(/var/www/php-fcgi-scripts/web366) is not within the allowed path(s) Somebody mentioned that earlier in this thread, but no solution was proposed (the error went away automagically in that case).
  35. 1 point
    I have found a solution and thought I would share it for the benefit of others. It may not be the most efficient or elegant solution but it is working. After some trial and error the solutions suggested in topic 7659, especially by formulate, began to make sense. In the tagging.php template file is the following code: $fullList = $pages->find("$searchTxt=$thisTag"); // this select all pages where page field "Tags" contains a page with title of our tag $tagList = $pages->find("$searchTxt=$thisTag, limit=10"); // this selects the same as above but limits the rsults for pagination $session->taggedPages=(string)$fullList; // save the result of the first search for use in the portfolio template In the portfiolio.php template file the following gets the prev / next pages from the tag search: $fullList=$pages->find("id=" .$session->taggedPages); $next = $page->next($fullList); $prev = $page->prev($fullList); This means that going to the prev / next page is not limited to those paginated on the tagging page. I hope that makes sense and helps someone else.
  36. 1 point
    Thank you @ceberlin for the link. I just looked into the article and will take a look at the tools they provide and how they work - hopefully this week. Those can easily be set in the texts you already show in the banner. That's how I do it most of the time.
  37. 1 point
    You can even skip the first few steps when you add PW as a "one click app". Either with or without Composer. https://processwire.com/talk/topic/21796-one-click-processwire-in-laragon/?tab=comments#comment-187287
  38. 1 point
    One simple way to do this client side with normal fields would be to add an "Active languages" field to each Repeater Matrix type, and use that as a language activation switch. For example: Create a Page Reference field "active_languages" with the template "language" as selectable pages and the input field type set to checkboxes. Then add that field to each repeater matrix type. Finally, in the code that renders the matrix item, use something like this (code untested): // assuming the matrix field name is "sections" foreach ($page->sections as $section) { $if ($section->matches("active_language={$user->language->id}") { // render the field } } Now the editor can check which languages they want the section to be displayed in. Obviously you can also invert the logic and use the checkboxes to hide the section in a specific language. Of course, having this built in would simplify things a lot 🙂
  39. 1 point
    Hey, I've tried a search but couldn't find anything about this precisely. Is there any explicit setting to add images to the start of an image field rather than the end on upload? I'm assuming I'll need to figure this out with hooks. Please ignore. Noob mistake asking a question from a client, they weren't drag dropping and I had a brain spasm.
  40. 1 point
    If you allow the user to select one or more products, you can use a select field to present the options to the user. Of course it depends on the number of available products. If there are a large number of products, you may want to separate them by category. The select field's options allow for values that you require.
  41. 1 point
    Thank you very much @Robin S, I have been able to fix the issue! 🙂
  42. 1 point
    Thanks @wbmnfktr good suggestion. I did already try this though, logged into the cms on Firefox and with an incognito windo open in Chrome to view the front end site. Thanks
  43. 1 point
    ProCache does that and is worth every cent: https://processwire.com/store/pro-cache/#procache-css-and-js-minification-and-merge https://modules.processwire.com/modules/pro-cache/
  44. 1 point
    Thank you very much for sharing, I have been trying to implement the option of "replying" in the comments for several weeks, I am quite close with the help provided by a user from this community. Do you know if this option is available for this uiKIT profile?
  45. 1 point
    Thank you, Pixrael! That got me to the solution! $loadLogo = $getKV->exhibitor_logo; $logoresize = $loadLogo->pim2Load('ig')->canvas(1600,895,array(0, 0, 0, 0),'c',0)->setOutputFormat("png")->pimSave()->httpUrl; $exlogo = $logoresize; $filename = $getKV->name . "_instagram.png"; $background = "https://domain.com/site/templates/images/Exhibitor-Graphic-BG-Platinum.jpg"; $logo = file_get_contents("$exlogo"); $bg = file_get_contents("$background"); $im = new \Imagick(); $im->readImageBlob($bg); $im2 = new \Imagick(); $im2->readImageBlob($logo); $im->compositeImage($im2, \Imagick::COMPOSITE_ATOP, 100, 350); $im->setImageFormat("png24"); $im->scaleImage(1024, 1024, true); $im->writeImage("../downloads/$filename"); $im->clear(); $im->destroy(); $file = "https://domain.com/site/downloads/$filename"; echo "<img src='$file' alt='$getKV->name' />"; Now I just need to bring in the code to start with a different background graphic based on the order history in Padloper. In THEORY, I'm almost there! 😅 Thanks so much for your help!
  46. 1 point
    We recently rebuilt the Architekturführer Köln (architectural guide Cologne) as a mobile-first JavaScript web app, powered by VueJS in the frontend and ProcessWire in the backend. Concept, design and implementation by schwarzdesign! The Architekturführer Köln is a guidebook and now a web application about architectural highlights in Cologne, Germany. It contains detailled information about around 100 objects (architectural landmarks) in Cologne. The web app offers multiple ways to search through all available objects, including: An interactive live map A list of object near the user's location Filtering based on architect, district and category Favourites saved by the user The frontend is written entirely in JavaScript, with the data coming from a ProcessWire-powered API-first backend. Frontend The app is built with the Vue framework and compiled with Webpack 4. As a learning exercise and for greater customizability we opted to not use Vue CLI, and instead wrote our own Webpack config with individually defined dependencies. The site is a SPA (Single Page Application), which means all internal links are intercepted by the Vue app and the corresponding routes (pages) are generated by the framework directly in the browser, using data retrieved from the API. It's also a PWA (Progressive Web App), the main feature of which is that you can install it to your home screen on your phone and launch it from there like a regular app. It also includes a service worker which catches requests to the API and returns cached responses when the network is not available. The Architekturführer is supposed to be taken with you on a walk through the city, and will keep working even if you are completely offline. Notable mentions from the tech stack: Vue Vue Router for the SPA functionality VueX for state management and storage / caching of the data returned through the API Leaflet (with Mapbox tiles) for the interactive maps Webpack 4 for compilation of the app into a single distributable Babel for transpilation of ES6+ SASS & PostCSS with Autoprefixer as a convenience for SASS in SFCs Google Workbox to generate the service worker instead of writing lots of boilerplate code Bootstrap 4 is barely used here, but we still included it's reboot and grid system Backend The ProcessWire backend is API-only, there are no server-side rendered templates, which means the only PHP template is the one used for the API. For this API, we used a single content type (template) with a couple of pre-defined endpoints (url segments); most importantly we built entdpoints to get a list of all objects (either including the full data, or only the data necessary to show teaser tiles), as well as individual objects and taxonomies. The API template which acts as a controller contains all the necessary switches and selectors to serve the correct response in <100 lines of code. Since we wanted some flexibility regarding the format in which different fields were transmitted over the api, we wrote a function to extract arbitrary page fields from ProcessWire pages and return them as serializable standard objects. There's also a function that takes a Pageimage object, creates multiple variants in different sizes and returns an object containing their base path and an array of variants (identified by their basename and width). We use that one to generate responsive images in the frontend. Check out the code for both functions in this gist. We used native ProcessWire data wherever possible, so as to not duplicate that work in the frontend app. For example: Page names from the backend translate to URLs in the frontend in the form of route parameters for the Vue Router Page IDs from ProcessWire are included in the API responses, we use those to identify objects across the app, for example to store the user's favourites, and as render keys for object lists Taxonomies have their own API endpoints, and objects contain their taxonomies only as IDs (in the same way ProcessWire uses Page References) Finally, the raw JSON data is cached using the cache API and this handy trick by @LostKobrakai to store raw JSON strings over the cache API. Screenshots
  47. 1 point
    You mean like this? Seems you missed the eligibility screen 😀. The GUI is not yet complete. The details are: Specific Groups of Customers New customers (have never bought something) Returning customers (have previously bought something) Abandoned checkouts Customers from own country (will probably change this to 'from specific countries') Newsletter (customers signed up to newsletter - this may not make it in the first release though + I haven't decided whether newsletter should be part of Padloper or not or third party, etc) Specific Customers Here you will select specific customers. These will have to be registered customers
  48. 1 point
    UPDATE OK, after I've faced that for and against again, I've decided to make the module freely available. If you are interested, you can test the current state of development. I already put the module on GitHub. Please note that the software is not yet intended for use in a production system. (Alpha version). For example, the configuration and handling of the VAT rates are still missing. Also the dashboard is still incomplete. And many other things needs to be improved and implemented... 🙂 If you like, you can also submit feature requests and suggestions for improvement. I also accept pull requests. https://github.com/gadgetto/SnipWire
  49. 1 point
    If it was me editing the pages, I could live with it, but for regular users is confusing. Not to mention paying customers .
  50. 1 point
    sure, here are some examples, i have these in a file called schema_helpers.php, which is in my shared functions folder: 1.) function siteSchema() { $page = wire('page'); $schema = array( "@context" => "http://schema.org", "@type" => "Website", "url" => wire('pages')->get(1)->httpUrl, "name" => $page->title, "description" => '', "potentialAction" => array( "@type" => "SearchAction", "target" => wire('pages')->get(1000)->httpUrl . "?q={search_term}", "query-input" => "required name=search_term" ), "about" => array( "@type" => "Thing", "name" => "A very interesting THING", "description" => "Website about a very interesting THING" ) ); if($page->summary) { $schema['description'] = $page->summary; } else { unset($schema['description']); } return '<script type="application/ld+json">' . json_encode($schema) . '</script>'; } 2.) News function jsonldNews($item, $settings) { $image = $item->image ?: getFallbackImage($item); if(!$image) return; $out = ''; $jsonld = array(); $jsonld["@context"] = "http://schema.org/"; $jsonld["@type"] = "NewsArticle"; $jsonld["name"] = $item->title; $jsonld["headline"] = $item->title; $jsonld["url"] = $item->httpUrl; $jsonld["mainEntityOfPage"] = array( '@type' => "WebPage", '@id' => $item->httpUrl ); $jsonld["description"] = $item->summary; $jsonld["datePublished"] = date(DATE_ISO8601, $item->published); $jsonld["dateModified"] = date(DATE_ISO8601, $item->modified); $jsonld["dateline"] = date(DATE_ISO8601, strtotime($item->news_date)); $jsonld["wordCount"] = str_word_count($item->body); $jsonld['author'] = $settings['author']; $jsonld['publisher'] = $settings['entity']; $jsonld['articleBody'] = $item->body; $jsonld['articleSection'] = $item->categories_select->first()->title; // Publisher $pubLogo = wire('pages')->get(3525)->image; if($pubLogo) { $pubLogo = $pubLogo->height(60); $jsonld['publisher'] = array( '@type' =>'Organization', 'name' => 'A Publisher', 'url' => 'https://publisher.org/', 'logo' => array ( '@type' => 'ImageObject', 'url' => $pubLogo->httpUrl, 'height' => $pubLogo->height, 'width' => $pubLogo->width ) ); } // News Items may have a featured image $image = $image->width(696); $jsonld['image'] = array( "@type" => "ImageObject", 'url' => $image->httpUrl, 'height'=> $image->height, 'width' => $image->width ); $out .= '<script type="application/ld+json">' . json_encode($jsonld) . '</script>'; return $out; } 3.) Event function jsonldEvent($event) { if(!$event->event_location_select) return; if($event->template == 'event-child') { // inherit unset fields needed $event->event_link = $event->event_link ? : $event->parent->event_link; $event->body = $event->body ? : $event->parent->body; $event->event_location_select = $event->event_location_select ? : $event->parent->event_location_select; $event->price = $event->price ? : $event->parent->price; $event->currency_code = $event->currency_code ? : $event->parent->currency_code; $event->link = $event->link ? : $event->parent->link; } $out = ''; foreach($event->event_date_m as $ed) { $jsonld = array(); $date8601 = date(DATE_ISO8601, strtotime($ed)); $jsonld["@context"] = "http://schema.org/"; $jsonld["@type"] = "MusicEvent"; $jsonld["name"] = $event->title; $jsonld["url"] = $event->event_link; $jsonld["description"] = $event->body; $jsonld["startDate"] = $date8601; if($event->event_location_select) { $state = $event->event_location_select->state ? $event->event_location_select->state->title : $event->event_location_select->address_state; $jsonld["location"] = array( "@type" => "Place", "name" => $event->event_location_select->title, "url" => $event->event_location_select->link, "address" => array( "@type" => "PostalAddress", "streetAddress" => $event->event_location_select->address_street, "addressLocality" => $event->event_location_select->address_city, "addressRegion" => $state, "postalCode" => $event->event_location_select->address_zip, "addressCountry" => $event->event_location_select->country->title ) ); } if($event->price && $event->currency_code && $event->link) { $jsonld["offers"] = array( "@type" => "Offer", "description" => "Tickets", "price" => $event->price, "priceCurrency" => $event->currency_code, "url" => $event->link ); } $out .= '<script type="application/ld+json">' . json_encode($jsonld) . '</script>'; } return $out; } Also - I don't think you need to use JSON_PRETTY_PRINT
  • Create New...