Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/09/2015 in all areas

  1. Hello, Here is a security related feature request. I am having more and more use of $page->id as a GET or POST parameter, for various workflows in frontend site. Processwire itself is making use of it at some places related to frontend, eg. for comments submission workflow. My problem is : This is an absolute AND predictable value : from 0 to N. So, when used for submission by the users, it allows a malicious user to forge requests in order to perform a FULL crawling of the website pages. Even pages that are otherwise not accessible by following the website links. Of course, Processwire access permissions apply ; but then, any site-specific permission weakness will result in information disclosure. Overall, this is not very satisfying. What would be best, instead, is the ability to make use of an absolute AND NOT predictable value : a $page->encodedId (build with something like http://hashids.org/php/) Along with a commodity method getDecodedId(), for retreiving the associated $page->id. Fact is, I am doing something similar to this in the templates which need it. And, for easier usage, I plan to generalize this to all templates, with some coding which implies hooks on template creation & on page creation, for automatically adding a $page->encodedId field at each template creation + automatically populating its value at each page creation/cloning. But before I go into this, I would like to submit this feature request : I would rather have this in Processwire core Processwire itself would directly benefit from this feature (see comments submission workflow, for instance). I hope it makes sense for someone else than me cheers
    3 points
  2. I know this may be more of a "Pro" feature right now, but PageTables could really sport the AJAX editing option like ListerPro, maybe even just for enabled fields. In some cases the PageTable might be quite narrow where only a small select option should be editable and a field with a more spacious inputfield should not be editable.
    2 points
  3. @adrian Success!!! I have completely migrated a wordpress blog into a ProcessWire site running the Blog module! I will be writing a quick summary and explainer on how to successfully do this. I am sure there are others who are going to encounter this at one point. It will be nice to save a headache and get it done quickly.
    2 points
  4. One notable difference between setOutputFormatting() and of() is the difference in return value. // setOutputFormatting is chainable and returns the page object $page->setOutputFormatting(false)->set("field", "value")->save(); // of() is not chainable, but does return the previous OutputFormatting status $oldOf = $page->of(false); $page->set("field", "value"); $page->save(); $page->of($oldOf);
    2 points
  5. --------------------------------------------------------------------------------------------------------------------------------- when working with PW version 2.6+, please use Pim2, not Pim! read more here on how to change from the older to the newer version in existing sites --------------------------------------------------------------------------------------------------------------------------------- PageImage Manipulator, API for version 1 & 2 The Page Image Manipulator is a module that let you in a first place do ImageManipulations with your PageImages. - And in a second place there is the possibility to let it work on any imagefile that exists in your servers filesystem, regardless if it is a 'known PW-image'. The Page Image Manipulator is a Toolbox for Users and Moduledevelopers. It is written to be as close to the Core ImageSizer as possible. Besides the GD-filterfunctions it contains resize, crop, canvas, rotate, flip, sharpen, unsharpMask and 3 watermark methods. How does it work? You can enter the ImageManipulator by calling the method pim2Load(). After that you can chain together how many actions in what ever order you like. If your manipulation is finished, you call pimSave() to write the memory Image into a diskfile. pimSave() returns the PageImage-Object of the new written file so we are able to further use any known PW-image property or method. This way it integrates best into the ProcessWire flow. The three examples above put out the same visual result: a grayscale image with a width of 240px. Only the filenames will slightly differ. You have to define a name-prefix that you pass with the pimLoad() method. If the file with that prefix already exists, all operations are skipped and only the desired PageImage-Object gets returned by pimSave(). If you want to force recreation of the file, you can pass as second param a boolean true: pim2Load('myPrefix', true). You may also want to get rid of all variations at once? Than you can call $pageimage->pim2Load('myPrefix')->removePimVariations()! A complete list of all methods and actions are at the end of this post. You may also visit the post with tips & examples for users and module developers. How to Install Download the module Place the module files in /site/modules/PageImageManipulator/ In your admin, click Modules > Check for new modules Click "install" for PageImageManipulator Done! There are no configuration settings needed, just install and use it. Download (version 0.2.0) get it from the Modules Directory History of origins http://processwire.com/talk/topic/3278-core-imagemanipulation/ ---------------------------------------------------------------------------------------------------------- Page Image Manipulator - Methods * pimLoad or pim2Load, depends on the version you use! pimLoad($prefix, $param2=optional, $param3=optional) param 1: $prefix - (string) = mandatory! param 2: mixed, $forceRecreation or $options param 3: mixed, $forceRecreation or $options return: pim - (class handle) $options - (array) default is empty, see the next method for a list of valid options! $forceRecreation - (bool) default is false It check if the desired image variation exists, if not or if forceRecreation is set to true, it prepares all settings to get ready for image manipulation ------------------------------------------------------------------- * setOptions setOptions(array $options) param: $options - (array) default is empty return: pim - (class handle) Takes an array with any number valid options / properties and set them by replacing the class-defaults and / or the global config defaults optionally set in the site/config.php under imageSizerOptions or imageManipulatorOptions. valid options are: quality = 1 - 100 (integer) upscaling = true | false (boolean) cropping = true | false (boolean) autoRotation =true | false (boolean) sharpening = 'none' | 'soft' | 'medium' | 'strong' (string) bgcolor = (array) css rgb or css rgba, first three values are integer 0-255 and optional 4 value is float 0-1, - default is array(255,255,255,0) thumbnailColorizeCustom = (array) rgb with values for colorize, integer -255 - 255 (this can be used to set a custom color when working together with Thumbnails-Module) outputFormat = 'gif' | 'jpg' | 'png' (Attention: outputFormat cannot be specified as global option in $config->imageManipulatorOptions!) set {singleOption} ($value) For every valid option there is also a single method that you can call, like setQuality(90), setUpscaling(false), etc. ------------------------------------------------------------------- * pimSave pimSave() return: PageImage-Object If a new image is hold in memory, it saves the current content into a diskfile, according to the settings of filename, imagetype, targetFilename and outputFormat. Returns a PageImage-Object! ------------------------------------------------------------------- * release release() return: void (nothing) if you, for what ever reason, first load image into memory but than do not save it, you should call release() to do the dishes! ? If you use pimSave() to leave the ImageManipulator, release() is called automatically. ------------------------------------------------------------------- * getOptions getOptions() return: associative array with all final option values example: ["autoRotation"] bool(true) ["upscaling"] bool(false) ["cropping"] bool(true) ["quality"] int(90) ["sharpening"] string(6) "medium" ["targetFilename"] string(96) "/htdocs/site/assets/files/1124/pim_prefix_filename.jpg" ["outputFormat"] string(3) "jpg" get {singleOption} () For every valid option there is also a single method that you can call, like getQuality(), getUpscaling(), etc. See method setOptions for a list of valid options! ------------------------------------------------------------------- * getImageInfo getImageInfo() return: associative array with useful informations of source imagefile example: ["type"] string(3) "jpg" ["imageType"] int(2) ["mimetype"] string(10) "image/jpeg" ["width"] int(500) ["height"] int(331) ["landscape"] bool(true) ["ratio"] float(1.5105740181269) ["bits"] int(8) ["channels"] int(3) ["colspace"] string(9) "DeviceRGB" ------------------------------------------------------------------- * getPimVariations getPimVariations() return: array of Pageimages Collect all pimVariations of this Pageimage as a Pageimages array of Pageimage objects. All variations created by the core ImageSizer are not included in the collection. ------------------------------------------------------------------- * removePimVariations removePimVariations() return: pim - (class handle) Removes all image variations that was created using the PIM, all variations that are created by the core ImageSizer are left untouched! ------------------------------------------------------------------- * width width($dst_width, $sharpen_mode=null) param: $dst_width - (integer) param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you prioritize the width, like with pageimage. Additionally, after resizing, an automatic sharpening can be done with one of the three modes. ------------------------------------------------------------------- * height height($dst_height, $sharpen_mode=null) param: $dst_height - (integer) param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you prioritize the height, like with pageimage. Additionally, after resizing, an automatic sharpening can be done with one of the three modes. ------------------------------------------------------------------- * resize resize($dst_width=0, $dst_height=0, $sharpen_mode=null) param: $dst_width - (integer) default is 0 param: $dst_height - (integer) default is 0 param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you have to set width and / or height, like with pageimage size(). Additionally, after resizing, an automatic sharpening can be done with one of the three modes. ------------------------------------------------------------------- * stepResize stepResize($dst_width=0, $dst_height=0) param: $dst_width - (integer) default is 0 param: $dst_height - (integer) default is 0 return: pim - (class handle) this performs a resizing but with multiple little steps, each step followed by a soft sharpening. That way you can get better result of sharpened images. ------------------------------------------------------------------- * sharpen sharpen($mode='soft') param: $mode - (string) possible values 'none' | 'soft'| 'medium'| 'strong' return: pim - (class handle) Applys sharpening to the current memory image. You can call it with one of the three predefined pattern, or you can pass an array with your own pattern. ------------------------------------------------------------------- * unsharpMask unsharpMask($amount, $radius, $threshold) param: $amount - (integer) 0 - 500, default is 100 param: $radius - (float) 0.1 - 50, default is 0.5 param: $threshold - (integer) 0 - 255, default is 3 return: pim - (class handle) Applys sharpening to the current memory image like the equal named filter in photoshop. Credit for the used unsharp mask algorithm goes to Torstein Hønsi who has created the function back in 2003. ------------------------------------------------------------------- * smooth smooth($level=127) param: $level - (integer) 1 - 255, default is 127 return: pim - (class handle) Smooth is the opposite of sharpen. You can define how strong it should be applied, 1 is low and 255 is strong. ------------------------------------------------------------------- * blur blur() return: pim - (class handle) Blur is like smooth, but cannot called with a value. It seems to be similar like a result of smooth with a value greater than 200. ------------------------------------------------------------------- * crop crop($pos_x, $pos_y, $width, $height) param: $pos_x - (integer) start position left param: $pos_y - (integer) start position top param: $width - (integer) horizontal length of desired image part param: $height - (integer) vertical length of desired image part return: pim - (class handle) This method cut out a part of the memory image. ------------------------------------------------------------------- * canvas canvas($width, $height, $bgcolor, $position, $padding) param: $width = mixed, associative array with options or integer, - mandatory! param: $height = integer, - mandatory if $width is integer! param: $bgcolor = array with rgb or rgba, - default is array(255, 255, 255, 0) param: $position = one out of north, northwest, center, etc, - default is center param: $padding = integer as percent of canvas length, - default is 0 return: pim - (class handle) This method creates a canvas according to the given width and height and position the memory image onto it. You can pass an associative options array as the first and only param. With it you have to set width and height and optionally any other valid param. Or you have to set at least width and height as integers. Hint: If you want use transparency with rgba and your sourceImage isn't of type PNG, you have to define 'png' as outputFormat with your initially options array or, for example, like this: $image->pimLoad('prefix')->setOutputFormat('png')->canvas(300, 300, array(210,233,238,0.5), 'c', 5)->pimSave() ------------------------------------------------------------------- * flip flip($vertical=false) param: $vertical - (boolean) default is false return: pim - (class handle) This flips the image horizontal by default. (mirroring) If the boolean param is set to true, it flips the image vertical instead. ------------------------------------------------------------------- * rotate rotate($degree, $backgroundColor=127) param: $degree - (integer) valid is -360 0 360 param: $backgroundColor - (integer) valid is 0 - 255, default is 127 return: pim - (class handle) This rotates the image. Positive values for degree rotates clockwise, negative values counter clockwise. If you use other values than 90, 180, 270, the additional space gets filled with the defined background color. ------------------------------------------------------------------- * brightness brightness($level) param: $level - (integer) -255 0 255 return: pim - (class handle) You can adjust brightness by defining a value between -255 and +255. Zero lets it unchanged, negative values results in darker images and positive values in lighter images. ------------------------------------------------------------------- * contrast contrast($level) param: $level - (integer) -255 0 255 return: pim - (class handle) You can adjust contrast by defining a value between -255 and +255. Zero lets it unchanged, negative values results in lesser contrast and positive values in higher contrast. ------------------------------------------------------------------- * grayscale grayscale() return: pim - (class handle) Turns an image into grayscale. Remove all colors. ------------------------------------------------------------------- * sepia sepia() return: pim - (class handle) Turns the memory image into a colorized grayscale image with a predefined rgb-color that is known as "sepia". ------------------------------------------------------------------- * colorize colorize($anyColor) param: $anyColor - (array) like css rgb or css rgba - but with values for rgb -255 - +255, - value for alpha is float 0 - 1, 0 = transparent 1 = opaque return: pim - (class handle) Here you can adjust each of the RGB colors and optionally the alpha channel. Zero lets the channel unchanged whereas negative values results in lesser / darker parts of that channel and higher values in stronger saturisation of that channel. ------------------------------------------------------------------- * negate negate() return: pim - (class handle) Turns an image into a "negative". ------------------------------------------------------------------- * pixelate pixelate($blockSize=3) param: $blockSize - (integer) 1 - ??, default is 3 return: pim - (class handle) This apply the well known PixelLook to the memory image. It is stronger with higher values for blockSize. ------------------------------------------------------------------- * emboss emboss() return: pim - (class handle) This apply the emboss effect to the memory image. ------------------------------------------------------------------- * edgedetect edgedetect() return: pim - (class handle) This apply the edge-detect effect to the memory image. ------------------------------------------------------------------- * getMemoryImage getMemoryImage() return: memoryimage - (GD-Resource) If you want apply something that isn't available with that class, you simply can check out the current memory image and apply your image - voodoo - stuff ------------------------------------------------------------------- * setMemoryImage setMemoryImage($memoryImage) param: $memoryImage - (GD-Resource) return: pim - (class handle) If you are ready with your own image stuff, you can check in the memory image for further use with the class. ------------------------------------------------------------------- * watermarkLogo watermarkLogo($pngAlphaImage, $position='center', $padding=2) param: $pngAlphaImage - mixed [systemfilepath or PageImageObject] to/from a PNG with transparency param: $position - (string) is one out of: N, E, S, W, C, NE, SE, SW, NW, - or: north, east, south, west, center, northeast, southeast, southwest, northwest default is 'center' param: $padding - (integer) 0 - 25, default is 5, padding to the borders in percent of the images length! return: pim - (class handle) You can pass a transparent image with its filename or as a PageImage to the method. If the watermark is bigger than the destination-image, it gets shrinked to fit into the targetimage. If it is a small watermark image you can define the position of it: NW - N - NE | | | W - C - E | | | SW - S - SE The easiest and best way I have discovered to apply a big transparency watermark to an image is as follows: create a square transparent png image of e.g. 2000 x 2000 px, place your mark into the center with enough (percent) of space to the borders. You can see an example here! The $pngAlphaImage get centered and shrinked to fit into the memory image. No hassle with what width and / or height should I use?, how many space for the borders?, etc. ------------------------------------------------------------------- * watermarkLogoTiled watermarkLogoTiled($pngAlphaImage) param: $pngAlphaImage - mixed [systemfilepath or PageImageObject] to/from a PNG with transparency return: pim - (class handle) Here you have to pass a tile png with transparency (e.g. something between 150-300 px?) to your bigger images. It got repeated all over the memory image starting at the top left corner. ------------------------------------------------------------------- * watermarkText watermarkText($text, $size=10, $position='center', $padding=2, $opacity=50, $trueTypeFont=null) param: $text - (string) the text that you want to display on the image param: $size - (integer) 1 - 100, unit = points, good value seems to be around 10 to 15 param: $position - (string) is one out of: N, E, S, W, C, NE, SE, SW, NW, - or: north, east, south, west, center, northeast, southeast, southwest, northwest default is 'center' param: $padding - (integer) 0 - 25, default is 2, padding to the borders in percent of the images length! param: $opacity- (integer) 1 - 100, default is 50 param: $trueTypeFont - (string) systemfilepath to a TrueTypeFont, default is freesansbold.ttf (is GPL & comes with the module) return: pim - (class handle) Here you can display (dynamic) text with transparency over the memory image. You have to define your text, and optionally size, position, padding, opacity for it. And if you don't like the default font, freesansbold, you have to point to a TrueTypeFont-File of your choice. Please have a look to example output: http://processwire.com/talk/topic/4264-release-page-image-manipulator/page-2#entry41989 ------------------------------------------------------------------- PageImage Manipulator - Example Output
    1 point
  6. Hey, Been using this starter theme for a little while now and thought I'd open it up on github - https://github.com/benbyford/bb-starter It has all my favourite modules installed, .less, some hany .js libraries and a set of blog templates for a simple news / blog setup. The theme is built on the simple theme from PW with additional setup. For more info see the Readme.md file on github. See it here - http://bbstarter.nicegrp.com/ Thanks everyone for your continued work and fun using PW.
    1 point
  7. Because I wanted to be able to strip all line breaks from a textarea field and then apply the Thinspace textformatter, I forked Netcarver’s module, added the required line and simply called it “Thinspace Plus” (which is not very creative, I know): https://github.com/MichaelvanLaar/PW-TextformatterThinspacePlus I use this Textformatter mostly for textarea fields that contain meta descriptions and similar content. The reason I use textarea fields here – instead of simple Text fields – is that I want to be able to use the great Textarea Counter module with these fields. But since these fields are intended to be simple strings without any line break or paragraph formatting, I want to “flatten” them – just in case an editor enters a line break. OK, the line breaks probably won’t do any harm in meta descriptions, OpenGraph descriptions, etc. But I just want to see them in my rendered source code ;-)
    1 point
  8. +1 for this request. While it's always in the hands of the dev to prevent malicious access to content, even if someone does fiddle with some id's, it's still an added layer of obstruction. This can for example be handy when using id's on the frontend site, like as urlSegments.
    1 point
  9. @adrian almost there! Had to change the template migrator settings now changing the field settings. Should have it figured out soon.
    1 point
  10. $copyYear doesn't need to be an integer. It's only compared to a string value, so it can just stay in a text field.
    1 point
  11. I am also looking for this as a fieldtype, because I have a Repeater field for different products with ratings. Also I want to integrate this with the comments fieldtype. How would I do that? I found https://processwire.com/talk/topic/10107-fieldtypestarrating/ as an alternative, which is a fieldtype, but it doesn´t handle floats (average ratings) and has no option to use the star rating on the frontend (rating and saving to database).
    1 point
  12. I'd suggest you read the first three of those linked topics here: http://processwire.com/api/multi-language-support/ The URL one does explain how you'd get those urls without doing anything to the .htaccess file. The first one does explain how the internationalization of static texts in templates work and the middle one is about how you can setup the fields for your dynamic content, so everything is language aware, too.
    1 point
  13. Comonly i create list > item template combinations. Like agenda list containing agenda items as children, or a news list containing news items. Now in most cases the list templates title would be set once (Agenda / News) and after that does not have to be editable (or my wish to be hidden). For that it would be nice to have an extra choice in the field visibility settings: Open when blank, hidden when populated So that while creating the page, the developer can set the title whichafter it wont be shown anymore, thus not being able to modify it. I can do this manualy, create all the list pages and then modify the template setting the title field to hidden for the specific fieldgroup.
    1 point
  14. Minor note regarding the 404 monitor: currently all hits to sitemap.xml (generated by Pete's Markup Sitemap XML module) are recorded as 404s. Haven't had a proper look under the hood yet, but so far I'm guessing that both modules hook into pageNotFound, in which case this sounds like a priority issue or the logger not checking if another module has modified the output (however that should be implemented). Anyway, just something you might want to consider for the new 404 logger module. For the record, the 404 logger is very handy when migrating a lot of content from one site to another, and it's also cool that one can easily register a new Jumplink from the 404 list. Great work, just like the rest of this module!
    1 point
  15. Simply put, there is absolutely no reason to go with Drupal in the situation you described. ProcessWire can easily handle your requirements. As a bonus, you will have fun at it! I'll also clear few misconceptions. ProcessWire can easily handle hundreds of thousands of pages, so you don't need to worry about that. What you need to worry about is the design of your templates, fields and relations. Making wrong selections there can severely impact the performance of the site. And even then, the community is happy to help if you face performance issues User registration won't be a problem either since users in PW are basically just pages. You can even extend the built-in 'user'-template with more fields.
    1 point
  16. you may be able to use $config class for your custom site variables;
    1 point
  17. Since admin themes are modules, the templates-admin serves as a fallback in case no AdminTheme modules are able to be loaded for one reason or another. That admin theme is there so that you can still login and fix your system if everything goes haywire for whatever reason… though I don't know of many scenarios where that would be the case, but consider it an insurance plan. Since it's there, it also serves as a good location for files that must be shared among all admin themes (whether the AdminTheme modules, or the fallback theme, or an older /site/templates-admin/). For example, the inputfields.js file, the debug.inc file, font-awesome, and possibly more in the future. It serves this purpose well and I don't see any reason to get rid of it. We may update it at some point to change the look of it, but also don't see it as much of a priority since nobody ever sees it except in rare development situations. Lastly, it's the only thing that enables use of older /site/templates-admin/ themes, for those that need to use the older system of admin themes for one reason or another (like folks that have company-customized admin themes from long ago, but still want to use a newer PW version).
    1 point
  18. Part III: Using YAML (part of structured data module). 1.) Install the module (make sure to install the new version, FieldtypeDataStructure) 2.) create the field for it (ex. settings_ds) 3.) Add some settings - these can be more sophisticated/nested than the settings above, because of the YAML structure options: - name: address street: 27 Hawthorne Lane city: New York state: NY zip: 10982 phones: main: (999) 888 9874 fax: (555) 548-5647 - name: social_media facebook: https://www.facebook.com twitter: https://twitter.com - name: global site_title: My Awesome Site tagline: Tulips Rule 4.) Get the field into your template: $settings_ds = $pages->get(1644)->settings_ds; 5a.) Option 1: Auto populate the $vars foreach($settings_ds as $setting) ${$setting->name} = $setting; 5b.) Option 2: Query the field with PW selectors (this is awesome): $address = $settings_ds->get("name=address"); $social_media = $settings_ds->get("name=social_media"); $global = $settings_ds->get("name=global"); this is cool because you can keep all the parts of a setting together as a group, and have multiple parameters like this: // address echo $address->street; echo $address->city; echo $address->state; echo $address->zip; echo $address->phones->main; echo $address->phones->fax; // social media echo $social_media->facebook; echo $social_media->twitter; // global echo $global->site_title; echo $global->tagline;
    1 point
  19. Part II: Using a Profields Table [Note: this part requires you to own ProFields] 1.) Setup a field of type table for settings, I call it settings_table. It will have 2 columns, setting and value 2.) add it to your template (example would be if you had a settings template). 3.) Add some settings.. | site_title | My Great Site | |------------|-------------------------| | phone | (666) 777-8888 | |------------|-------------------------| | slogan | Tulips Rule | |------------|-------------------------| | facebook | http://www.facebook.com | 3.) Place this code in your _init.php or wherever you have global stuff.. replace the page number with the appropriate page number: $settings_table = $pages->get(1020)->settings_table; foreach($settings_table as $row) { ${$row->setting} = $row->value; } now you can do this: echo $site_title echo $phone echo $slogan echo $facebook - - - ...and one might wonder, what is to prevent a client from inadvertently changing the setting name or even deleting a critical setting and consequently breaking their site? with some jQuery, and the help of admin custom files (courtesy of martijn-geerts) you can disable any existing setting name from being edited. or deleted; add this to your AdminCustomFiles/ProcessPageEdit.js file: $(function(){ $('li.Inputfield_settings_table tr').each(function(){ setting = $(this).find('input[name*="_setting"]'); value = $(this).find('input[name*="_value"]').val(); icon = $(this).find('i.InputfieldTableRowDeleteLink'); if(value) { setting.addClass("disabled").attr('readonly', true); icon.removeClass("InputfieldTableRowDeleteLink fa-trash-o").addClass("fa-lock"); } }); }); this does assume that the table is named settings_table, the setting column is named "setting" and the value column is named "value". you can also add this to your AdminCustomFiles/ProcessPageEdit.css li.Inputfield_settings_table tr input.disabled { background-color: #e8e5e5 !important; color: #949494!important; } Here is a screenshot of this in action: Edit: added instructions to protect the settings names, prevent deletion, and change the color to differentiate the field status.
    1 point
  20. Would something like this work? (written in browser, so might need tweaking). This should print all events sorted by date descending, but grouped by day and sorted by time ascending within the day. $allEvents = $pages->find("parent=/events/, sort=-date"); while($allEvents->count()) { $event = $allEvents->first(); $from = strtotime(date('Y-m-d 00:00', $event->getUnformatted('date'))); $to = strtotime("+1 day", $from); $events = $events->find("date>=$from, date<$to, sort=date"); echo "<h3>Events on " . date('F j, Y', $from) . "</h3>"; foreach($events as $event) { echo "<p><a href='$event->url'>$event->title</a> $event->date</p>"; $allEvents->remove($event); } }
    1 point
×
×
  • Create New...