Jump to content

kongondo

PW-Moderators
  • Posts

    7,475
  • Joined

  • Last visited

  • Days Won

    144

Everything posted by kongondo

  1. Downloading Media From Media Manager Library I was recently asked whether it was possible to download media already uploaded to Media Manager. Currently, there is no automated way to do this. However, using the ProcessWire API, one can achieve this. Below is a starter code showing how one can download image media from Media Manager. I'll consider adding this feature to Media Manager. Please note that I have deliberately left Tracy debugging statements in the code. You will want to wrap this around a check if user is Superuser. // get limited number of media manager images $mmPages = $pages->find('template=media-manager-image, limit=10'); $tempName = 'media_manager_downloads';// temporary name for folder to place images in // 1. MAKE DIRECTORY // @note: could have used $files->tempDir('hello-world'); but not working for some reason // create a new directory in ProcessWire's cache dir $copyTo = $config->paths->cache . $tempName; if($files->mkdir($copyTo)) { // directory created: /site/assets/cache/media_manager_downloads/ // 2. COPY IMAGES // get and copy image assets foreach($mmPages as $p) { $images = $p->media_manager_image; foreach($images as $image) { //bd($image->filename,'image path')// to debug image path $copyFrom = $image->filename; $bool = $files->copy($copyFrom, $copyTo); //bd($bool,'copied?');// just to test if files were copied } } // 3. ZIP IMAGES // if files were copied, zip them if(!empty($files->find($copyTo))){ // create zip of all files in directory $copyTo to file $zip $zip = $config->paths->cache . "media-manager-image-files.zip"; $result = $files->zip($zip, $copyTo); echo "<h3>These files were added to the ZIP:</h3>"; foreach($result['files'] as $file) { echo "<li>" . $sanitizer->entities($file) . "</li>"; } if(count($result['errors'])) { echo "<h3>There were errors:</h3>"; foreach($result['errors'] as $error) { echo "<li>" . $sanitizer->entities($error) . "</li>"; } } // 4. SEND FILES TO BROWSER FOR DOWNLOADING // if files were added to zip file, send them if(!empty($result['files'])){ bd($zip,'files were added'); $files->send($zip); } } else { bd('NO FILES FOUND!'); } } Hope this helps.
  2. Maybe you could consider Media Manager ??
  3. Yes. They are for both. If using resizing feature, the images will be constrained to those limits. If they fall short of the minimum, the images are discarded. If not using resizing, original images should meet the minimum and maximum constraints. Good idea. I'll see how to better word this. I am coming up blank at the moment ?
  4. Actually, there is ?. See under Settings > Upload Settings > Image. There are settings for min/max height and min/max width. These are directly coupled to the the field's (media_manager_image) corresponding settings. If you change one it will change the other. However, I have just noticed a bug. The min values are decoupled! This shouldn't matter much though since Media Manager will still honour the min values. I will fix these later (i.e. the 'decoupling' issue). Excellent suggestion! I will add this to my TODO as well. NO ETA for above, just yet, sorry. I hope it isn't urgent? Thanks!
  5. Welcome to the forums @Neeraz, It was decided early on to add classes to the <li> instead of the <a>, as it was the usual practice. Getting the <a> via CSS is quit easy, for instance... #menu li a { /* your styles here*/ } You can be as specific as you want with your CSS. Not a good idea as this will get overwritten next time you upgrade Menu Builder :-).
  6. Should be $file->filename or $file->filename() :-)
  7. Hmm. This is a tricky one as it is made up of two parts: Paying a fraction (instalment) of the total cost Future payment (aka recurring payment) Both are tricky, but especially #2. #1 is partly achievable by raising an invoice using manual order creation. The order will be manually marked as complete once the total has been paid. Automating the process may not be an easy task. I'd have to think about it more. # 2 If this means storing user card details, then no; we are not going down that route. However, if it means using payment providers' subscription/recurring payments services, then it is probably doable. The payment providers API is there. Something else to think about, but for future versions. Currently none of these features are in the plan, but I'll have a think. I will probably need reminding though :-).
  8. You mean like in a spreadsheet? You mean including the page values of the fields as well or just the field definitions?
  9. The response I was going to give is aptly summarised by @gornycreative (quoted below...) It would be a nightmare to keep track of global freight. We will provide hooks on our side to facilitate this. However, whilst we will strive to cater for different scenarios, we will prioritise making sure the API works for the bigger providers first and/or the most popular (with respect to our client base). Please note that this (and other advanced features will be incrementally added to Padloper 2 but will certainly not make it in the first release). This is not currently planned. It might make it on my to do list for future releases, depending on demand. No. This is not planned. It might be considered depending on demand, though. Thanks! ?
  10. Update: Menu Builder 0.2.7 Changelog Added the property extra_fields for use with getMenuItems() ONLY. This enables returning the page field values for some selected Fieldtypes. For example, the description field in the page corresponding to the menu item. Thanks @e0f for the inspiration. Full documentation of this new feature is available here. Menus in multi-lingual sites can now be called using their multi-lingual titles or names irrespective of the current user's language. For example, a multi-lingual site with English, German and Finnish languages could have a menu with the respective titles My Awesome Menu / Mein Tolles Menü / Oma Mahtava Valikko. Any of these titles can be used in the code to call the menu (using render() or getMenuItems() methods). [PS: blame you-know-who for these language translations :-)] Changed the way new menus are added. Only one menu can be added at a time. The title field/input is multi-lingual ready. See screens below. Improved the backend GUI when viewing locked menus. Only the menu items and and exit button are shown in such cases. Fixed bug that allowed access to unpublished menus for frontend rendering. Updated the documentation Refactored code to improve efficiency. In dev branch only for testing. Screenshots a. Add Menu (Multi-lingual) b. Edit Menu (Multi-lingual) c. Locked Menu d. An example usage of extra_fields (I am no designer, so yeah, nothing much to see here...but you get the idea :-)) Thanks for testing!
  11. Maybe not what you need, but could be worth looking at the new module Dashboard?
  12. Hi @e0f, Currently, this is not doable out of the box. However, using the method getMenuItems() (see a few posts up for examples), you can use the property pagesID (or index pages_id if getting back array of menu items) to get ($pages->get($m->pageID), for example) the respective ProcessWire pages of the menu items and return the custom fields you want, e.g. description. Having said that, I would not recommend this. It seems like an overkill and may not be very performant based on the number of menu items and other factors. Perhaps if you could explain your use case, I would see if I can add an option to retrieve the values of simple fields (text, integers, dates, etc) for use with getMenuItems(). MenuBuilder is primarily for building navigation menus. From your example, it seems you are using it for a different purpose? Maybe provide a fuller example so that I can get my head around this.
  13. Anything that repeats in any programming language calls for, invariably, something you can iterate/traverse (e.g. an array) and the tool you use for the traversal/looping, (e.g. foreach). Let's go with these two. Looking at the UIkit markup you've pasted, I suppose some of the classes are automatically injected by UIkit JavaScript. However, the basic structure of the markup that repeats is the same. Hence, I'll ignore markup classes for now. The main differences in the images ratio markup are the following: The main containers for the images vary in the class they have. The first, the second and the fourth have the class: <div class="uk-width-expand@s">...</div> The 3rd image container has a different class: <div class="uk-width-2-3@s">...</div> Secondly, the <img> markup themselves have different values for their data-height attribute. Hence, we will need some variable to store these differences. Although some of the values are shared, for instance, the class for the main images container for the 1st, 2nd and 4th images (as stated above), I prefer to store each image's values separately. This can help down the line if the markup changes resulting in different values that were previously identical. Although it may be simple to assume that the images in your image field (which I will refer to as images) are already arranged in order and are in the correct size, from experience, we know that this will most likely NOT be the case. Clients can upload images that are not of the correct size and arrange them randomly. You may need to cater for this, e.g. have the clients tag the images with first, second, etc....but that may be too much work. OK, for the fun part. Please note that in the examples below, I only focus on the images' container part. I have also left in the CSS just for reference, although they may be auto-injected as stated above. We have at least two ways to loop through our images. Both ways involve having an array that will have 4 nested arrays, one each for our 4 images. The first way to loop through our images is to loop through the images themselves and access the array with images info inside this loop as shown below: The main downside to the above approach is we are assuming there will always be four images in the images field. What if a client adds more? What if there are less images? All these will require adding checks in the code (within the loop) to check how many images we have. To counter some of these challenges, we can instead loop through the array with the info for images as shown below: This is just basic code to get you started. There are a number of things that could be improved. For instance, you may want ProcessWire to resize the images for you (done once) rather than depending on your browser to contain larger images. See the Resize and crop section in the API documentation here. There are alternative approaches as well to the examples shown above. PS: code untested
  14. HTML specs say select tag does not have readonly attribute. Use disabled instead. I think a disabled select will not POST though.
  15. @gebeer, Not sure if you know that a similar module shares the same class name as yours (FieldtypeImagePicker). I don't know if @theo's module is still being maintained. It also does not seem to be in the module's directory. It may not be an issue but just good to know, just in case.
  16. Why does this have to be Multi Select? Shouldn't it be either checked or not (i.e a single select?) Aah, I see, it seems you have different status? Correct. If that's the case, it is better to use Pages:saved. However, please further explain your scenario, i.e. If a page is already set to booked, but it is edited, should an email be resent? What is booked? Is it the name of a page? What if a booking is cancelled, is an email to be sent?
  17. @gebeer You might want to clean-up some of the copy-paste inline comments that shipped with the example code from your module's code ?
  18. Great! Btw.. You don't need to set inbuilt ProcessWire columns like 'pages_id in your getDatabaseSchema() :-). ProcessWire will do it automatically. Same with extra, unless you really are adding something extra. Thanks for confirming! ??
  19. Oops. I was looking at the wrong file, so not sure if you are currently doing this? If not, here are examples: public function ___wakeupValue(Page $page, Field $field, $value) { // some code... // start a blank value to be populated $myClassWireArray = $this->getBlankValue($page, $field); // if we were given a blank value, then we've got nothing to do: just return a blank MyClassWireArray if(empty($value) || !is_array($value)) return $myClassWireArray; // create new myClassObj objects from each item in the array foreach($value as $v) { $myClassObj = new MyClass(); // @note we're converting 'data' to 'property1' (this is the filename) $myClassObj->property1 = $v['data']; $myClassObj->property2 = $v['column_2']; $myClassObj->property3 = $v['column_3']; $myClassObj->setTrackChanges(true); $myClassWireArray->add($myClassObj); } $myClassWireArray->resetTrackChanges(); return $myClassWireArray; } public function ___sleepValue(Page $page, Field $field, $value) { $sleepValue = array(); // some code.... // convert each MyClassObj to an array within sleepValue foreach($value as $myClassObj) { $sleepValue[] = array( 'data' => $myClassObj->property1, // @note: property1 is becoming data (this is the filename) 'column_2' => (int) $myClassObj->property2, 'column_3' => (int) $myClassObj->property3 ); } return $sleepValue; }
  20. You might also need something like this in your getMatchQuery() // if normal sql characters, do 'normal' query, else do fulltext search if($this->wire('database')->isOperator($operator)) { return parent::getMatchQuery($query, $table, $subfield, $operator, $value); } else { $ft = new DatabaseQuerySelectFulltext($query); $ft->match($table, $subfield, $operator, $value); return $query; }
  21. Try ___getSelectorInfo(). Grep wire folder for full examples. Here's some example code. @see the label index in the code. <?php /** * Get information used for InputfieldSelector interactive selector builder * * This is for Lister purposes. * We want nice labels for our lister selects (i.e. not raw db ones, i.e. 'some_column'). * * @param Field $field The field we are working with. * @param array $data Array of extra data, when/if needed. * @return array * */ public function ___getSelectorInfo(Field $field, array $data = array()) { $info = parent::___getSelectorInfo($field, $data); ## filterable subfields for this field ## // we get rid of the subfield 'data' instead, we'll use 'custom one' => IF APPLICABLE TO YOU! if(isset($info['subfields']['data'])) unset($info['subfields']['data']); // unset misc_data (example column we don't need in filter) if(isset($info['subfields']['misc_data'])) unset($info['subfields']['misc_data']); $subfields = array( // @note: @see getMatchQuery! // text column example 'some_text_column' => array( 'name' => 'some_text_column', 'input' => 'text', 'label' => $this->_('My Text Column'),// NICE LABEL FOR LISTER // @note: comment out those that don't make sense! 'operators' => array('%=', '!%=', '*=', '!*=', '~=', '!~=', '^=', '!^=', '$=', '!$=', '=', '!=', '=""', '!=""'), 'options' => array(), ), // number column example 'some_number_column' => array( 'name' => 'some_number_column', 'input' => 'number', 'label' => $this->_('My Number Column'), // @note: commented out those that don't make sense 'operators' => array('=', '!=', /*'<', '>', '<=', '>=',*/ '=""', '!=""'), 'options' => array(), ), ); $info['subfields'] = array_merge($info['subfields'], $subfields); return $info; } If it doesn't work, I'll need to dig a litter deeper...
  22. Yes it should (but test ?). Just remember that in your getDatabaseSchema() for data, you will need to set correct column type (text or varchar, etc) and the correct index type (fulltext most likely if using text).
  23. Yes it is, unless something changed that I am not aware of. In __sleepValue() and __wakeupValue() convert it from/to your property and in getMatchQuery() make sure to pass the correct $subfield (as you are currently doing in both respects). What are you currently using data for? pageid? Please show us an example search.
  24. Yeah. You can do a lot of fancy stuff in wakeupValue(). You can even create run time values and add them as properties in your $field object, or even fetch data elsewhere and add these as runtime properties, etc.
×
×
  • Create New...