Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/29/2014 in all areas

  1. Today we launched a new website www.pluimveeweb.nl. This is our first portal page build in ProcessWire is all about poultry. Partners of pluimveeweb can have their own Microsite within the site. There are several different sources where information is comming from, imported to ProcessWire, managed in the backend and make it ready for articles. It is quite a big project worked the last 3 months on it. Here ya go: pluimveeweb
    5 points
  2. There you go. Pushed a new version to GitHub and updated modules directory + opening post accordingly. Changed the name to Admin Save Actions (though the damage has been done). Don't know how this affects those trying to update the module via ModulesManager - probably you need to remove and reinstall the module, sorry for that. Added "edit next sibling page" as described in some of the earlier posts. Basically does what Kongondo's version does too - a bit different route though. There's also a config option to set a safety net for this: option will not be show if there are more siblings (defaults to 100). Option is not shown also when there is no next sibling available (root page or last visible and published page under this parent). @Martijn: I didn't go for hidden/unpublished pages at this time. But I'm thinking of modifying this a bit so that when the edited page is hidden/unpublished also siblings are searched with "include=all". Do you think that would be logical?
    3 points
  3. My take if($page->parents->has($section)) ... if($section->find("id=$page")->count()) ... // direct parent-child if($section->children("id=$page")->count()) ... if($page->parent === $section) ...
    3 points
  4. ...I went ahead and hackishly implemented my feature request (edit next sibling) . Seems to work OK? Code: Github Short demo: Feature only implemented for pages minus "home", "hidden" and "unpublished". User is redirected (with a status message) to the page list when there is no next sibling to edit...I used page->next. Btw, I don't understand this quote ...I thought page->next will only grab one page (i.e. it is not an array but an object?)...
    3 points
  5. Thanks for the input guys! I made a (classic, for me at least) mistake trying to make other modifications at the same time and ended up not publishing any of my changes. But Kongondo's code and Martijn's comments both revealed some things I hadn't taken into account. I'll try and publish the changes as soon as possible but I won't promise anything as it seems I never keep them anyway. Sorry. That possible performance issue is not solved just by using selector version of next(). The problem is we've got no general form of selector that would for sure limit the pages getting loaded there. Like Martijn explained, all the siblings have to be loaded to find out the current page's place among them before it's possible to say which page would be the next (no way to do this in the database, without stored procedures at least ). So using "limit" is not the answer here as you'd only get an incomplete PageArray possibly not even including the current page. I'm trying to get there by offering "edit next sibling page" as an option only if there are less than 100 siblings (could be made configurable of course). This way there's always a safe net to make sure editing a page doesn't slow down too much because of this module.
    2 points
  6. I had no idea about apeisa's project. His code is easy to read, so I might just figure out how to modify that and in the process learn about how to make modules in the process. It looks surprisingly simple. Thanks Adrian.
    2 points
  7. A couple of PW modules: https://github.com/jdart/FieldTypeRate https://github.com/apeisa/CommentRatings Also some other relevant forum posts: http://processwire.com/talk/topic/2126-rudimentary-5-star-rating-system/ http://processwire.com/talk/topic/3630-need-slight-variation-on-existing-module/ Hope something in those is helpful.
    2 points
  8. Hi, After reading this thread, I decided to make a module that helps generating PDF files of ProcessWire pages. GitHub: https://github.com/wanze/Pages2Pdf Modules Directory: http://modules.processwire.com/modules/pages2-pdf/ This module uses the mPDF library to generate the PDF files. It has fully UTF-8 and basic HTML/CSS support for rendering the PDF files. The output is customizable with ProcessWire templates. Example I've enabled generating PDF files for the skyscraper template of ryans Skyscrapers-profile with a template that outputs the data in a table along with the body text and the images: one-atlantic-center-pdf-4177.pdf Please take a look at the README on GitHub for instructions and further information/examples. Cheers
    1 point
  9. This basic tutorial is primarily aimed at those new to PW. It could also serve as a reference to others more seasoned PW users. The question about how to categorise content comes up in the forums now and again. Hopefully with this post we’ll have a reference to guide us right here in the tutorials board. Many times we need to organise our site content into various categories in order to make better sense of the data or to logically and easily access it. So, how do you organise your data when you need to use categories? Here are a few tips gathered from the PW forums on how to go about this. Using these tips will, hopefully, help you avoid repeating yourself in your code and site content and keep things simple. See the links at the end of this post to some useful discussion around the topic of categorisation. Before making decisions about how to organise your site, you need to consider at least three questions: What items on my site are the main items of interest? These could be people or things (cars, plants, etc.). In most cases, these are the most important content on which all the other stuff point to. Where do items need to be grouped into categories? This is about where items need to “live”. It is about the attributes of the items of interest (e.g. responsibilities, job types, colour, etc.). Attributes can have sub-attributes (e.g. a category job type = driver could be further sub-classified as job type role = train driver). Can they live in more than one place? - This is about having multiple attributes. There could be other issues such as the type of content your main items of interest are but that’s for another post. We’ll keep these examples simple. The main principles explained below still apply. There are at least three possible ways in which you can organise your content depending on your answers to the above three questions. These are: Single category Simple multiple categories Complex multiple categories These are illustrated below. Note that this is what I call them; these are not PW terms. 1. Single Category Suppose you need to do a site for a company that’s made up of several Departments each with employees performing unique functions. These could include “Finance”; “Media Communications”; “Administration”; “Technicians”; “Human Resources”; “Logistics”. We ask ourselves the following questions based on our 3 questions above: 1. Q: What items on my site are the main items of interest? A: Employees. 2. Q: What attributes of our items of interests are we interested in? A: Departments. (Single main category) 3. Do the Departments have sub-categories? A: Yes. (Multiple sub-categories) 4.Can Employees belong to multiple sub-categories? A: No. (Single sub-category) We conclude that what we need is a Single Category model. Why? This is because, in Single Categories model, items of interest can only belong to 1 and only 1 main/parent category and within that only 1 sub-category Employees in this company can only belong to one and only one department. Finance guys do their finance and Logistics guys do their stuff. Letting Techies do press conferences is probably not going to work; that we leave to the Media guys . Assuming the company has the following employees - James, John, Mary, Ahmed, Peter, Jason, Barbara etc., arranging our site content to fit this model could look like the following: Items of interest = Employees Categories = Departments Adopting out strategy to keep it simple and logical, let us write down, hierarchically, our employee names against their departments to mimic the PW tree like this: James Finance John Finance Mary Technician Ahmed Logistics Barbara Media Etc. We notice, of course, that departments start repeating. It doesn't look like we are doing this very logically. If we think about this carefully, we will conclude that, naturally, the thing (attribute in this case) that keeps repeating should be the main criteria for our categorisation. This may seem obvious, but it is worth pointing out. Also, remember, that as per the responses to our questions, the categories (Finance, Logistics, etc.) do not have sub-categories. In this aspect, we are OK. Using this principle about repeating attributes, we find that Departments, rather than Employees, need to be the main categories. Hence, we categorise our PW site content by doing the following. Create a template for each Department. Hence, we have a template called Finance, Logistics, etc. Add the fields needed to those templates. This could be a text field for holding Employee phone numbers, email field for email, title field for their names, etc. Create top level pages for each Department and assign to them their respective templates. Give them appropriate titles, e.g., Finance, Media, etc. Create a page for each employee as a child page of the Department which they belong to. Give them appropriate titles, e.g. James, John, etc. We end up with a tree that looks like this: 1. Finance (ex. main category) a. James (ex. item of interest) b. John c. Shah d. Anne 2. Logistics (ex. main category) a. Ahmed b. Matthew c. Robert d. Cynthia 3. Media a. Barbara b. Jason c. Danita 4. Human Resources a. Michael b. Pedro c. Sally 5. Technician a. Mary b. Oswald c. Dmitri d. Osiris Since an employee can only belong to one Department, our work here is done. We can then use PW variables, e.g. $page->find, $pages->find with the appropriate selectors to find employees within a Department. This is a very basic example, of course, but you get the idea. You have the choice of creating one template file for each category template as well. I prefer the method of using one main template file (see this thread). You could do that and have all Departments use different templates but a single template file. In the template file you can include code to pull in, for example, the file “technician.inc” to display the relevant content when pages using the template “Technician” are viewed. Example code to access and show content in Single Categories model $hr = $pages->find("template=human-resources, limit 50"); foreach ($hr as $h) { echo "{$h->title}"; } But sites do not always lend themselves to this model. Many times, items of interest will need to belong to multiple categories. 2. Simple Multiple Categories Let’s say you were building a site for cars - red cars, blue cars, 2-seaters, 5-seaters, etc. Again, we ask ourselves our questions based on our initial three questions: 1. Q: What items on my site are the main items of interest? A: Cars. 2. Q: What attributes of our items of interests are we interested in? A: Colour, Number of seats, Models, Year of manufacture, Types. (Multiple categories) 3. Do these multiple attributes have sub-attributes? A: Yes. e.g., the attribute Colour has several sub-categories - red, white, green, etc. (Multiple sub-categories) 4. Can Cars have multiple sub-attributes? A: No. e.g., a yellow car cannot be a green car. (Single sub-categories) We therefore conclude that what we need is a Simple Multiple Category model. Why? This is because, in Simple Multiple Categories, items of interest can belong to multiple parent categories. However, within those parent categories, they can only belong to one sub-category. Assuming we have the following cars, manufactured between 2005 and 2008, as items of interest: Mercedes, Volvo, Ford, Subaru, Toyota, Nissan, Peugeot, Renault, Mazda, arranging our site content to fit this model could look like the following: Items of interest = Cars Categories = Model, Year, Colour, Number of seats, Type Sub Categories = Model [Prius, etc.]; Year [2005, 2006, 2007, 2008]; Colour [Red, Silver, Black, White, Green]; Number of seats [2, 5, 7]; Types [sports, SUV, MPV]. Adopting out strategy to keep it simple and logical, if we wrote down our cars names against their attributes like this: Mercedes Model-Name: Year: 2005 Colour: Silver Seats: 2-seater Type: Sports Volvo Model-Name: Year: 2007 Colour: Green Seats: 5-seater Type: SUV Ford Model-Name: Year: 2007 Colour: Red Seats: 7-seater Type: MPV Etc We notice, again, that car attributes start repeating. In order not to repeat ourselves, we want to avoid the situation where our child pages “names” keep repeating. For instance, in the above example tree, we want to avoid repeating year, colour, etc. within the tree. Of course in the frontend our output needs to look like the above where we can list our cars and their respective attributes. We just don’t need a tree that looks like this in the backend. Since we have multiple categories and sub-categories, we need to rethink our strategy for categorising our content as illustrated below. The strategy we used in the first category model will not work well here. Hence, these repeating attributes (year, colour, etc.) need to be the main criteria for our categorisation. We need to end up with a tree that looks like this: 1. Cars a. Mercedes (ex. item of interest) b. Volvo c. Ford d. Subaru e. Toyota f. Range Rover g. Peugeot h. Renault i. Mazda 2. Model (ex. main category) a. Fiesta (ex. sub-category) b. Miata c. Impreza d. Matrix e. Prius f. E-Class g. XC-90 h. Scenic i. L322 j. 505 3. Year a. 2005 b. 2006 c. 2007 (ex. sub-category) d. 2008 4. Colour a. Red b. Silver c. Black d. White e. Green 5. Number of Seats a. 2 b. 5 c. 7 6. Type a. MPV b. Sports c. SUV d. Other At the top of the tree, we have our main items of interest, Cars. They do not have to come first on top of the tree like that but it just makes sense to have them like this. Next, we have the Cars’ categories (attributes). The main categories are parent pages. Each main category has children which act as its sub-categories (cars’ sub-attributes). For instance, the main category colour has sub-categories “red”, “green”, etc. Grouping them under their main category like this makes better sense than having them dangling all over the tree as parent pages themselves. Now that we know what we want to achieve, the next question is how do we go about relating our categories and sub-categories to our main items of interest, i.e., cars? Fields come to mind. OK, yes, but what about the sub-categories (2006, red, 5-seater, etc.)? Surely, we can’t keep typing those in text fields! Of course not; this is PW. We like to simplify tasks as much as we can. What we need is a special type of field. Page Reference Fields or Page Fieldtypes add the ability to reference other pages, either single or multiple pages, within a page. For instance, we could have a Page Reference Field in the template that our Car pages use. Let’s call this “car-template”. When viewing Car pages, we would have the ability to select other pages on our site that we wish to reference, for instance, because they are related to the page we are viewing. In other cases, we could also wish to reference other pages that contain attributes/values of the page we are viewing. This is the situation with our Cars example above. Hence, the sub-categories/sub-attributes for our Cars will be pulled into our car pages using Page Reference Fields. There are two types of Page Reference Fields; single page and multiple pages. What each do is obvious from their names. Single Page Reference Fields will only reference one page at a time. Multiple Page Reference Fields will reference multiple pages. OK, let’s go back to the issue at hand. We need to categorise Cars by various attributes. Do we need to reference the main categories (Year, Type, etc.) in our Car pages? In fact, we don’t. What we need to reference are the sub-categories, i.e. 2005, red, SUV, etc. These will provide the actual attributes regarding the parent attribute of the Cars. We have said we do not wish to type these sub-categories/attributes all the time hence we use Page Reference Fields. Which type of Page Reference Field should we use? Remember that our Cars can have only one sub-category/sub-attribute. That’s our cue right there. In order to select one and only one sub-attribute per Car, we need to use the single Page Reference Field. Hence, we categorise our Cars PW site by doing the following (you may follow a different order of tasks if you wish). Create a template to be used by the Car pages. Give it a name such as car-template Create a page for each of your cars and make them use the car-template Create one template to be used by all the main attribute/categories and their children (the sub-categories). We do not need a template for each of the categories/sub-categories. I name my template “car-attributes” Of course you can name yours differently if you wish. Add the fields needed to this template. You don’t need anything other than a title field for each actually. Create top level pages for each main category and assign to them the template car-attributes. As before, give your pages meaningful titles. Do the same respectively for their child pages. E.g., you should have the following child pages under the parent “Year” - 2005, 2006, 2007 and 2008. Create the Page Reference Fields for each of your main categories/parent attributes. Using our example, you should end up with 5 Page Reference Fields (model, year, colour, seats and type). Each of these should be single Page Reference Fields. It’s a good idea, under the BASICS settings while editing the fields, to include some Description text to, include additional info about the field, e.g. instructions. In addition, you don’t want any page that doesn't belong to a particular attribute to be selectable using any of the Page Reference Fields. For instance, when referencing the year a car was manufactured, we want to be able to only select children of the page Year since that is where the year sub-categories are. We do not want to be able to select children of Colour (red, green, etc.) as the year a car was manufactured! How do we go about this? PW makes this very easy. Once you have created your Page Reference Fields, while still in the editing field mode, look under the settings INPUT. The fourth option down that page is “Selectable Pages”. Its first child option is “Parent of selectable page(s)”. Where it says “Select the parent of the pages that are selectable” click on change to change the parent. By now you know where I am going with this. For the Page Reference Field named Year, choose the page “Year” as the parent whose children will be selectable when using that Page Reference Field to select pages. Similarly, do this for the remaining 4 Page Reference Fields. Note that under this field settings INPUT you can change how you want your pages to be selectable. Be careful that you only select the types that match single Page Reference Fields, i.e. the ones WITHOUT *. For single Page Reference Fields, you have the choices:Select - a drop down select Radio buttons PageListSelect Now edit the car-template to add all 5 of your Car Page Reference Fields. We are now ready to roll. Go ahead and edit your Car pages. In each of them you will see your 5 Page Reference Fields. If you followed the instructions correctly, each of them should only have the relevant child pages/sub-attributes as selectable. Do your edits - select year when car was manufactured, its colour, type, number of seats, etc. and hit Save. By the way, note that Page Reference Fields give you access to all the fields and properties of the page being referenced! You have access to the referenced page’s title, name, path, children, template name, page reference fields, etc. This is really useful when creating complex sites. I call it going down the rabbit hole! These properties of the referenced page are available to you on request. It does mean that you will have to specifically echo out the property you want from that page. Page Reference Fields are echoed out like any other field. Example code to access and show content in Simple Multiple Categories model $cars = $pages->find("template=car-template, limit=10, colour=red, year=2006, seats=5"); foreach ($cars as $car) { echo $car->title; echo $car->year; echo $car->colour; } I have made the above verbose so you can easily follow what I'm trying to achieve. The above code will find 10 red 5-seater cars manufactured in 2006. Remember, colour, year and seats are the names of your custom Page Reference Fields that you created earlier. Some sites will have content that belong to multiple categories and multiple sub-categories. We address this below. 3. Complex Multiple Categories Suppose you are developing a site for a school. The school has teachers (duh!) some of whom teach more than one subject. Besides their classroom duties, some teachers are active in various clubs. On the administration side, some teachers are involved in various committees. You know the drill by now. Let’s deal with our basic questions. 1. Q: What items on my site are the main items of interest? A: Teachers. 2. Q: What attributes of our items of interest are we interested in? A: Subjects, Administration, Clubs (Multiple categories) 3. Do these multiple attributes have sub-attributes? A: Yes. e.g., the attribute Subjects has several sub-categories - History, Maths, Chemistry, Physics, Geography, English, etc. (Multiple sub-categories) 4. Can Teachers have multiple sub-attributes? A: Yes. e.g., a Teacher who teaches both maths and chemistry (Multiple sub-categories) Apart from the response to the final question, the other responses are identical to our previous model, i.e. the Simple Multiple Categories. We already know how to deal with multiple categories so we’ll skip some of the steps we followed in the previous example. Since our items of interest (Teachers) can belong to more than one sub-category, we conclude that what we need is a Complex Multiple Category model. In Complex Multiple Categories, items of interest can belong to multiple parent categories and multiple sub-categories both within and without main/parent categories. By now we should know what will be the main criteria for our categorisation. We need to end up with a tree that looks like this: 1. Teachers a. Mr Smith (ex. item of interest) b. Mrs Wesley c. Ms Rodriguez d. Mr Peres e. Mr Jane f. Mrs Potter g. Ms Graham h. Mrs Basket i. Dr Cooper 2. Subjects (ex. main category) a. History (ex. sub-category) b. Maths c. English d. Physics e. Chemistry f. Geography g. Religion h. Biology i. French j. Music 3. Clubs a. Basketball b. Debate c. Football d. Scouts e. Sailing f. Writing 4. Administration a. Discipline b. Counselling c. Exams board d. Public relations e. Education We are ready to build our site. Which type of Page Reference Field should we use? Remember that our Teachers can teach more than one subject and can be involved in various sub-category activities. That’s our cue right there. In order to select multiple attributes/categories, we of course go for the multiple Page Reference Field. Similar to the previous example, create necessary templates and fields for the site. For our multiple Page Reference Fields, remember to select the correct input field types. These should match multiple Page Reference Fields and are marked with *. For multiple Page Reference Fields, the available choices are: Select Multiple* AsmSelect* Checkboxes* PageListSelectMultiple* PageAutoComplete* Remember to add the multiple Page Reference Fields to the Teachers template. Go ahead and test different selectors, e.g. find Teachers that teach Maths and Chemistry and are involved in the Writing club. Whether you get results or not depends on whether there is actually that combination. An important point to remember is that your multiple Page Reference Fields will return an array of pages. You will need to traverse them using foreach (or similar). Example code Complex Multiple Categories model Find the subjects taught by the Teacher whose page we are currently viewing. You can use if statements to only show results if a result is found. In this case, of course we expect a result to be found; if a Teacher doesn't teach any subject, he/she has no business teaching! subjects is the name of one of your custom Multiple Page Reference Fields. echo "<ul>"; foreach ($page->subjects as $x) { echo "<li>{$x->title}</li>"; } echo "</ul>"; There will be situations where you will need to use both Single and Multiple Page Reference Fields (independently, of course). For instance, in our Teachers example, we might be interested in the Gender of the Teacher. That would require a Single Page Reference Field. Summary What we have learnt: Categorising our site content need not be a nightmare if we carefully think it through. Of course not all sites will fit neatly into the 3 models discussed. By providing answers to a few simple key questions, we will be able to quickly arrive at a decision on how to categorise our content. There are at least 3 models we can adopt to categorise our content - single category; simple multiple category; and complex multiple category. In the latter two models, we make full use of PW’s powerful Page Reference Fields to mimic a relational database enabling us to roll out complex sites fast and easy. Useful links: http://processwire.com/talk/topic/3553-handling-categories-on-a-product-catalogue/ http://processwire.com/videos/create-new-page-references/ http://processwire.com/videos/page-fieldtype/ http://processwire.com/talk/topic/1041-raydale-multimedia-a-case-study/ http://processwire.com/talk/topic/683-page-content-within-another-page/ http://processwire.com/talk/topic/2780-displaying-products-category-wise/ http://processwire.com/talk/topic/1916-another-categories-question/ http://processwire.com/talk/topic/2802-how-would-you-build-a-daily-newspaper/ http://processwire.com/talk/topic/2519-nested-categories/ http://processwire.com/talk/topic/71-categorizingtagging-content/ http://processwire.com/talk/topic/2309-best-way-to-organize-categories-in-this-case/ http://processwire.com/talk/topic/2200-related-pages/ http://processwire.com/talk/topic/64-how-do-you-call-data-from-a-page-or-pages-into-another-page/
    1 point
  10. I'm having a weird issue with images in TinyMCE. When adding images to the images field (the default one), I add a description. Then I add the image to the body field via TinyMCE. Then save and the image has the correct alt text. So far so good... But, if I reopen the same image with the image button, the description is gone from the modal window. If I re-save, the image is displayed without the description. Looks like the image it's not retaining the original description value when editing. Is this a bug?
    1 point
  11. Looking great! Very nicely structured. Where are the minisites? Can't find them! Couldn't help but noticed a small typo: Martktprijzen
    1 point
  12. 1 point
  13. You can't login user, as you don't know the password. setCurrentUser does not login but set the current user, so if you do that for every request it's like he's logged in. To you original question I have no idea. Not something usual.
    1 point
  14. Hi Peter, Welcome to PW! I apologise as I am a bit tight on time here but needless to say this all sounds very do-able in PW. There are many different ways of going about it however. One such way is, as you say, to use the in-built users. My personal advice would be to create pages for your users. You could always tie them to user groups (other pages) through page reference fields. Each "cyclist" template could have the necessary fields (distance, groups etc). In terms of updating the statistics, it depends really though my preference would be to create "front-end forms" (create your own forms using ProcessWire's API) then you may create forms such as "Add Bike Ride" whereby you could choose who has completed it, how far it was... And then have control over what happens to the data. This could also be achieved by creating your own module and still using the admin side to add data. It's quite to hard to explain this and sometimes the best way is to try it out in a small way, then we can give you pointers as you go. If you do some searching of the forum you will see there have been quite a few similar projects
    1 point
  15. Hey all, Here's a new PW site we launched in the end of last week. The site is a active archive of research documents from the areas of urbanism and territory planning, and was commissioned by the University from Aveiro, in Portugal. Again, PW was invaluable to achieve exactly what we wanted, since we built a quite complex website that required almost no training to the client. We made a heavy use of page fields to achieve all the filtering effect on the documents page. Special mention to Aleo and Varela. Two beautiful typefaces. Hope you guys like it as much as we and the client do http://www.ordenaracidade.pt/ http://www.milktop.co.uk/projects/ordenar-a-cidade/
    1 point
  16. Come on Diogo, you know you want to
    1 point
  17. has_parent.... http://processwire.com/api/selectors/ http://cheatsheet.processwire.com/
    1 point
  18. You're on the right track, but not sure what all would be required to make ckeditor work on front-end. There's many js config vars used in the backend for certain fields like TinyMCE or CKeditor. If you look at admin source code you'll see the var config = { .... } in head, that can then be read by js scrpts and plugins. All this stuff is dynamic and pulls configs needed from the field configurations. This is populated via $config->js(); and output in the admin theme (default.php) before any scripts are includes. Also the scripts and styles needed for a particular Inputfield is loaded via $config->scripts and $config->styles, this is then again output in the admin theme (default.php) in the head. All these play together to make admin backend work in it's modularity.
    1 point
  19. It would be correct: $sanitizer->pageName("Größen", Sanitizer::translate); No it's not dependent on special thing. It's used to translate titles to the name. Nothing to do with translations. This was added at some point around 2.3 after lots discussion and isn't documented on API section (yet) but on cheatsheet http://cheatsheet.processwire.com/?filter=pagename.
    1 point
  20. Siblings are all loaded in memory. Say you have hundreds of siblings, next & prev has to find out where it is compared to his brothers. So have to load them all. If the list contains not much siblings, there's nothing wrong. A real time case case ( you actually build it ) will point out if it's still functioning well or not. It's not unlikely that we see more problems then that there actually are. The thing I needed, was the next unpublished sibling, as those pages came from automatic import (cron).
    1 point
  21. https://github.com/vhf/free-programming-books/blob/master/free-programming-books.md#php You're welcome.
    1 point
  22. btw. It would be so nice to learn more about how you did this. Don't you have time for a short tutorial? Sure, you don't :-(
    1 point
  23. @landitus, in my case i'm generating the page name initially because that will be overwritten when the person changes the fields on the page; in this case it's more of a database entry and not a page on the site. to change the page name and title on save (from a combination of fields) i use a module that was also demonstrated by Pete called 'buildUrl' i think and then i expanded it a lot
    1 point
  24. Sorry Nik, didn't read your post very well. I agree on the sibling issue. --- ps, customised your wonderful Module, ( + added some permission related things in it only useful in this instance ) I called it afterShaveActions. Thanks for creating AfterSaveActions. Love your coding style !
    1 point
  25. I still think this strategy would be fragile over time. It's not the job of a web service to keep track of deleted things, that's the job of the client accessing the service. I don't know of any major web service that attempts to bundle deleted items in a feed. The problems arise when something really does get deleted, and your web service has no record of it. If the client accessing your service expects you to keep track of all deleted items, then this will break sooner or later. You can't count on everything being in the trash. That is just a temporary container. Sooner or later it has to be deleted. Not to mention, showing deleted items in the feed means your feed has unnecessary overhead. The responsibility has to rest on the client side or else the system will break down at some point. Here's what I usually do on the client side: Keep two extra fields per record in the feed: import_id (integer) and import_time (unix timestamp). The import_id reflects the unique ID of each item from the feed, and is needed to connect items from the feed with your local items. The import_time reflects the timestamp of when the item was last updated. Before the feed is pulled, the client records the current timestamp and keeps it somewhere, like in a variable: $startTime = time(); Then they pull the feed, iterating through each item in the feed and updating or adding an associated page item for each. Note that the import_time of each page item is updated regardless of whether any changes occurred. You are essentially identifying all the items that are still active by updating their import_time field. $parent = $pages->get("/path/to/items/"); $http = new WireHttp(); $feed = $http->getJSON('http://domain.com/path/to/feed'); if(is_array($feed) && count($feed)) { foreach($feed as $data) { $item = $pages->get("import_id=$data[id]"); if(!$item->id) { // add new item $item = new Page(); $item->parent = $parent; $item->template = 'some-template'; $item->import_id = $data['id']; $item->save(); } else { $item->of(false); } // populate item $item->title = $data['title']; // ... // update import_time $item->import_time = time(); $item->save(); } // after importing the feed is complete, find the pages that were NOT updated // these pages may be deleted or trashed foreach($parent->children("import_time<$startTime") as $item) { $item->trash(); } } I like if the web service also provides an "exists" function, to determine that an item really has been deleted. This returns a thumbs up or down for each item requested, as to whether it exists or not. It's not entirely necessary, but it adds a little extra peace of mind as a backup in case something goes wrong. This is described in one of my posts above. Combined with the code above, the part that does the $item->trash() would just be preceded by a call to the exists feed to reduce the list of $items to only those that are confirmed to be deleted: // find which pages weren't updated $ids = array(); foreach($parent->children("import_time<$startTime") as $item) { $ids[] = $item->import_id; } // send the IDs of those pages back to the feed, asking it to confirm deletion $feed = $http->getJSON('http://domain.com/path/to/feed/exists?id=' . implode(',', $ids)); foreach($feed as $id => $exists) { if($exists === false) { // deletion confirmed, so page may be deleted $item = $pages->get((int) $id); $item->trash(); } } As for memory issues: any feed dealing with a lot of data needs to provide pagination of feed data (example), otherwise it will not be able to scale and will break if there is too much data. Pagination of a feed is a lot simpler than you'd expect for both the service and the consumer. It not much more than wrapping everything in a foreach.
    1 point
  26. I think the problem here is down to variable scope. When the code was in your template, it had direct access to ProcessWire pages using the system variable $pages. When you put this inside a function, it's no longer available. The way you can fix this is to change it to this: function kiddiMenu(){ $current_page = wire('pages')->get("/planning-your-journey"); $homepage = $current_page; $children = $homepage->children; echo "<ul class='' >"; foreach($children as $child) { $class = $child === wire('page')->rootParent ? " class='active'" : ''; echo "<li><a$class href='{$child->url}'><span class='l'></span><span class='r'></span><span class='t'>{$child->title}</span></a></li>"; } echo"</ul>"; } The difference is that $pages and $page (the variables that are out of scope) are replaced with global function calls which return the same thing, and are available from anywhere in ProcessWire. The ProcessWire system variables are listed here - variables. Any time you're in a function or a module, just replace them with a call to the wire() function with the name as the parameter. E.g. wire('input') for $input.
    1 point
  27. One of the next items on the to-do list for repeaters it to be able to specify a max number of items, but I'm not sure that would accomplish what you are looking for here. Your best bet may be a hook after ProcessPageEdit::processInput to look at the values of both fields. I would suggest setting your repeater "ready" items at 0, so that it is less to consider when counting the values. You could put this, or something like it at the top in your /site/templates/admin.php file: <?php wire()->addHookAfter('ProcessPageEdit::processInput', null, 'checkRepeaterQuantity'); function checkRepeaterQuantity($event) { $form = $event->arguments(0); // ProcessPageEdit's processInput function may go recursive, so we want to skip // the instances where it does that by checking the second argument named "level" $level = $event->arguments(1); if($level > 0) return; $select = $form->get("your_quantity_select_field"); if(!$select) return; $quantity = $select->attr('value'); $repeater = $form->get("your_repeater_field"); if(!$repeater) return; if(count($repeater) > $quantity) { $repeater->error("You have specified more than $quantity items"); } }
    1 point
  28. I agree that it does sound like unnecessary duplication. What's the benefit of creating your own users as pages separate from ProcessWire users? I'm not sure I understand the considerations there yet. But if you want to go that route and create your own pages as users, then there's probably no reason to maintain a 1-to-1 mapping with PW users. Instead, you can probably have a single user that you map all your own user pages to. Or perhaps a few separate PW users that you can map to, each with different levels of permissions... but then this is treating PW users as roles or groups, circumventing a system that's already there. I think the question of what users are may be the wrong question and instead it might be better to look at using the existing users system and what management additions are needed in your case. Perhaps modifying or extending the current ProcessUser module to provide the capabilities you need would be the simplest route.
    1 point
  29. PageImage Manipulator - Tips & Examples * how to create a PNG with transparency for the watermarkLogo method If you can use adobe photoshop, you simply may download and install this action: photoshop_action_PW-png-creations.zip create an empty image (transparent, not white or black) of 2000 x 2000 pixel write / paste your text and / or logo in a single color, (e.g. black) when finished with your text you should have one single layer with text on transparent background then click the action PW-png-creations -> 2000px-square-to-smooth and you are done. Hhm, maybe before saving you want to tweak the global transparency of the image a bit. That one used in the ProcessWire example was set to 75% instead of 100%. Just try out what looks best for you. ------------------------------------------------------------------- * did you know that you can save to different file formats, regardless of source format? You only have to specify your desired format (gif, jpg, png) with the optionally options array with a key named outputFormat and pass it with your call to pimLoad() or use setOptions() before any other action-method: // assuming the first image is a jpeg $img = $page->images->first(); // define outputFormat $options = array('outputFormat'=>'png'); // apply it together with other actions $myPng = $img->pimLoad('myPrefix')->setOptions($options)->width(240)->pimSave(); //------------------------------------------------------------------------------------------ // you may also do it as a OneLiner only with the image format conversion $myPng = $page->images->eq(0)->pimLoad('myPrefix', array('outputFormat'=>'png'))->pimSave(); // or you can use the setOutputFormat method $myPng = $page->images->first()->pimLoad('myPrefix')->setOutputFormat('png')->pimSave(); ------------------------------------------------------------------- * (how) can I use the ImageManipulator with other imagefiles than PW-Pageimages? You can load any imagefile from your servers filesystem into the ImageManipulator with: $pim = wire('modules')->get('PageImageManipulator')->imLoad($imageFilename); // or $pim = $wire->modules->get('PageImageManipulator')->imLoad($imageFilename, $options); You can directly with the imLoad-method pass specific $options or you can do a separate call to setOptions(). Then you do your desired actions and last but not least you call save()! Most time I think the original passed file gets overwritten with the manipulation result, but you are also able to save to a different name and / or fileformat. If so, it is useful to get the final (sanitized) filename back after saveing. $optionalNewFilename = $pim->setOptions($options)->height(360)->flip()->blur()->save(); Also you may call this in one line if you prefer: if(false!==$wire->modules->get('PageImageManipulator')->imLoad($imageFilename,$options)->height(360)->flip()->blur()->save()) { // success !! } ------------------------------------------------------------------- * how can I use the PageImageManipulator with my own module/s? If you build a module that do some image manipulation you can define the PIM as needed dependency in your ModulesInfo method with the key 'requires'. You may also force to install the PIM if it isn't already with the key 'installs': public static function getModuleInfo() { return array( // ... 'requires' => array('PageImageManipulator'), 'installs' => 'PageImageManipulator', // ... ); } detailed infos are here: http://processwire.com/talk/topic/778-module-dependencies/ additionally, if you need to check if a module dependency has a minimum version number, you can do it in your install method like this: public function ___install() { // check that at least the minimum version number is installed $needed = '0.0.3'; $a = wire('modules')->get('PageImageManipulator')->getModuleInfo(); $actual = preg_replace('/(\d)(?=\d)/', '$1.', str_pad("{$a['version']}", 3, "0", STR_PAD_LEFT)); if(version_compare($actual, $needed, '<')) { throw new WireException(sprintf($this->_(__CLASS__ . " requires PageImageManipulator %s or newer. Please update."), $needed)); return; } // ... more code } ------------------------------------------------------------------- * global options in site/config.php You can create a config-array in your site/config.php. If you look into it you will find a config array for the ImageSizer that comes with the PW core $config->imageSizerOptions = array( 'autoRotation' => true, 'sharpening' => 'soft', 'upscaling' => true, 'cropping' => true, 'quality' => 90 ); You can define another array with these keys: $config->imageManipulatorOptions = array( 'autoRotation' => true, 'sharpening' => 'soft', 'upscaling' => false, 'cropping' => true, 'quality' => 90, 'bgcolor' => array(255,255,255,0), ); You don't have to specify all of the options. PiM reads the imageSizerOptions and merge them with the imageManipulatorOptions. So if you want to have different values you can specify them in imageManipulatorOptions to override those from imageSizerOptions. Only one option isn't present with the imageSizer: bgcolor. This is only used by the imageManipulator. ------------------------------------------------------------------- * using PiM together with the awesome Thumbnails Module (http://mods.pw/1b) If you use the Thumbnails Module together with PiM, you can set two options in the site/config.php under imageManipulatorOptions: $config->imageManipulatorOptions = array( // ... 'thumbnailColorizeCustom' => array(40,-35,0), 'thumbnailCoordsPermanent' => true ); For the colorize dropdown select you can define the custom color here and with the second param you enable/disable permanent storage of RectangleCoords and params. The coords and params are stored with Thumbnails Module per session, but are lost after the session is closed. If you enable permanent storage these data is written into a custom IPTC field of the original imagefile. ------------------------------------------------------------------- * some more examples will folow here . . . -------------------------------------------------------------------
    1 point
  30. TinyMCE can be maddening sometimes in this respect, as I've tried adding allowed attributes only to have TinyMCE refuse them for some reason or another. It's almost as if there are some other rules at play overriding user defined ones. However, if you set TinyMCE to allow everything then it usually works. The way you do that is to set your valid_elements to this: *[*] Not saying that's a good solution, but it works in a pinch and sometimes it's the only way I can get TinyMCE to cooperate.
    1 point
  31. I find lynda.com has loads of great video series. It's helped me learn everything from HTML to PHP and if I had the time and patience, I could probably become a master of about 10,000 different pieces of software/languages!
    1 point
  32. Attached is an entire Fieldtype and Inputfield that show an example of 3 inputs for each image (title, tags and description). I've also set it up so that you can just change the schema in the getDatabaseSchema() function and it should automatically work with whatever varchar or text fields that you add. Though note that you'll want to make those changes before you create any fields with it. This works because the only place these custom fields are defined is in that schema, and everything else in the Fieldtype and Inputfield just picks it up from that schema. In the future, I will probably use this as a foundation for a more advanced image/file fieldtype where you can specify the schema from the field's configuration in the admin, rather than modifying the code. But figured this would be a good example for what you asked for. Ryan FieldtypeImageExtra.zip
    1 point
×
×
  • Create New...